Updated to v1.0.3 adding interactive tutorial.

master
Droog71 2022-01-06 23:32:41 -05:00
parent b680dff33e
commit f653f15027
38 changed files with 709 additions and 159 deletions

View File

@ -7,16 +7,12 @@ Your habitat has been constructed and your mining systems are operational.</br>
As a resident engineer, you must manage life support systems and</br>
mining equipment to ensure your income is adequate for survival.</br>
</br>
Expenses are deducted from your balance at regular intervals.</br>
The amount deducted increases as time goes on, increasing the</br>
difficulty of the game the longer you play.</br>
</br>
You can win the game by earning $30,000 and lose if you reach $10,000 in debt.</br>
These limits can be removed with the /unlimited console command.</br>
You must be granted server privileges to use this command, (ie: /grantme server)</br>
Expenses are deducted from your balance at regular intervals and</br>
are increased based on the total amount of ore you have mined.</br>
</br>
Moontest is playable in both single player and multiplayer game modes.</br>
</br>
</br>
<h2>Gameplay</h2>
<img src="https://i.imgur.com/C8vUbjb.png">
This is your <b>nuclear reactor</b>, the power source for your habitat.</br>
@ -101,4 +97,4 @@ energy is full then you will be moved to the lobby of the space habitat.</br>
This is your <b>research station</b>. Here, you can conduct research on organic matter</br>
'harvested' on the moon's surface. Organic matter is worth $10 each early in the game.</br>
This value increase each time you process research data. The limit is $50.</br>
To conduct research, left click the research station while holding the organic matter.
To conduct research, left click the research station while holding the organic matter.

View File

@ -0,0 +1,34 @@
--[[
Moon Habitat Simulator
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--
--defines the greeting formspec
local function greeting_formspec(player)
local greeting =
"Welcome to Moontest: Moon Habitat Simulator!\n" ..
"Press I to open your inventory.\n" ..
"Click the tutorial button there to start the tutorial.\n" ..
"Alternatively, click the manual button to read the manual.\n\n" ..
"Good luck and have fun!"
local formspec = {
"size[8.5,6]",
"bgcolor[#2d2d2d;false]",
"button_exit[3.25,5;2,0.5;OK;OK]",
"label[1.5,1;" .. greeting .. "]"
}
return formspec
end
--shows the greeting formspec
minetest.register_on_joinplayer(function(player)
local cb = function(player)
if not player or not player:is_player() then
return
end
local name = player:get_player_name()
minetest.show_formspec(name, "greeting", table.concat(greeting_formspec()))
end
minetest.after(2.0, cb, player)
end)

View File

@ -0,0 +1,2 @@
name = initial_message
description = Show message to joining players explaining what the game is about.

View File

@ -45,7 +45,7 @@ minetest.register_node("mesecons_button:button_off", {
}
},
groups = {dig_immediate=2, mesecon_needs_receiver = 1},
description = "Button",
description = "Button\n" .. "Momentarily energizes a logic circuit.",
on_rightclick = function (pos, node)
minetest.swap_node(pos, {name = "mesecons_button:button_on", param2=node.param2})
mesecon.receptor_on(pos, mesecon.rules.buttonlike_get(node))

View File

@ -81,7 +81,8 @@ if i > 1 then
end
local off_state = {
description = "Delayer",
description = "Delayer\n" .. "When energized, allows the logic signal\n" ..
"to continue after an adjustable delay.",
tiles = {
"mesecons_delayer_off_"..tostring(i)..".png",
"mesecons_delayer_bottom.png",

View File

@ -56,7 +56,7 @@ if nodename ~= "mesecons_microcontroller:microcontroller0000" then
end
minetest.register_node(nodename, {
description = "Microcontroller",
description = "Microcontroller\n" .. "A programmable logic gate.",
drawtype = "nodebox",
tiles = {
top,

View File

@ -1,5 +1,5 @@
minetest.register_node("mesecons_noteblock:noteblock", {
description = "Noteblock",
description = "Noteblock\n" .. "Emits a sound when energized.",
tiles = {"mesecons_noteblock.png"},
is_ground_content = false,
groups = {dig_immediate=2},

View File

@ -2,7 +2,7 @@
mesecon.register_node("mesecons_switch:mesecon_switch", {
paramtype2="facedir",
description="Switch",
description="Switch\n" .. "Used to turn logic circuits on and off.",
is_ground_content = false,
sounds = nil,
on_rightclick = function (pos, node)

View File

@ -203,7 +203,8 @@ local function register_wires()
end
mesecon.register_node(":mesecons:wire_"..nodeid, {
description = "Mesecon",
description = "Wire\n" .. "Used to connect relays to machines,\n" ..
"reactor boosters, delayers and micro-controllers.",
drawtype = "nodebox",
inventory_image = "mesecons_wire_inv.png",
wield_image = "mesecons_wire_inv.png",

View File

@ -3,6 +3,6 @@ Moontest
Moon habitat simulator.
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
Dependencies: none

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--
@ -11,29 +11,32 @@ local loading_timer = 0
local expense_timer = 0
local save_timer = 0
local computer_timer = 0
local previous_expense = 0
minetest.settings:set_bool("enable_fog", false)
minetest.settings:set_bool("menu_clouds", false)
minetest.settings:set_bool("smooth_lighting", true)
minetest.register_item(":", { type = "none", wield_image = "hand.png"})
skybox.add({"Space", "#FFFFFF", 0, { density = 0}})
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "nodes.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "habitat.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "oxygen.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "climate.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "hunger.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "energy.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "machines.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "interaction.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "simulation.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "reactor_booster.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "logic.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "aliens.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "research.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "sprint.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "hud.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "formspec.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "shop_formspec.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "nodes.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "habitat.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "oxygen.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "climate.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "hunger.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "energy.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "machines.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "interaction.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "simulation.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "reactor_booster.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "logic.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "aliens.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "research.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "sprint.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "hud.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "formspec.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "tutorial.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "shop_formspec.lua")
minetest.register_entity("moontest:alien", alien_definition)
@ -65,17 +68,14 @@ minetest.register_on_joinplayer(function(player)
initial_sprite_basepos = {x = 0, y = 0}
})
skybox.set(player, 1)
if not save_exists() then
local load_time = first_run() and 20 or 10
local load_time = first_run() and 20 or 10
minetest.after(load_time, function()
build_habitat()
player:set_pos(vector.new(0, 2, 5))
habitat_built = true
end)
elseif habitat_built == false then
if save_exists() then
load_world()
player:set_pos(vector.new(0, 2, 5))
habitat_built = true
end
end
end)
@ -211,10 +211,10 @@ end
--returns true on first run to increase loading time while media files are cached
function first_run()
if minetest.settings:get_bool("first_run") then
if minetest.settings:get_bool("moontest:first_run") then
return false
end
minetest.settings:set_bool("first_run", true)
minetest.settings:set_bool("moontest:first_run", true)
return true
end
@ -255,43 +255,52 @@ minetest.register_globalstep(function(dtime)
loading_timer = 0
end
else
if loaded == false then
add_hud_message("Game started.")
loaded = true
end
update_oxygen()
update_hunger()
update_energy()
update_climate()
update_machines()
update_simulation()
update_shared_hud()
spawn_aliens()
expense_timer = expense_timer + 1
if expense_timer >= 1000 then
money = money - math.floor(total_ore_mined * 0.01)
update_money_hud()
add_hud_message("Expenses paid: " .. "$" .. math.floor(total_ore_mined * 0.01))
add_hud_message("Expenses increased to: " .. "$" .. math.floor(total_ore_mined * 0.01))
if aggro < 1 then
aggro = aggro + 0.01
end
expense_timer = 0
if loaded == false then
add_hud_message("Game started.")
loaded = true
end
if tutorial_active == false then
update_oxygen()
update_hunger()
update_energy()
update_climate()
update_machines()
update_simulation()
update_shared_hud()
spawn_aliens()
save_timer = save_timer + 1
if save_timer >= 100 then
save_game()
save_timer = 0
end
computer_timer = computer_timer + 1
if computer_timer >= 20 then
update_computer_formspec()
computer_timer = 0
end
end
expense_timer = expense_timer + 1
if expense_timer >= 1000 then
local expense = math.floor(total_ore_mined * 0.01)
money = money - expense
update_money_hud()
add_hud_message("Expenses paid: " .. "$" .. expense)
if expense > previous_expense then
add_hud_message("Expenses increased to: " .. "$" .. expense)
previous_expense = total_ore_mined * 0.01
end
if aggro < 1 then
aggro = aggro + 0.01
end
expense_timer = 0
end
save_timer = save_timer + 1
if save_timer >= 100 then
save_game()
save_timer = 0
end
computer_timer = computer_timer + 1
if computer_timer >= 20 then
update_computer_formspec()
computer_timer = 0
end
else
update_energy()
update_shared_hud()
end
end
end)
--restarts the game

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--

View File

@ -1,12 +1,13 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--
energy_levels = {}
sleeping = {}
local energy_timer = 0
local fatigue_timer = 0
local sleep_timer = 0
--initializes the energy variable
minetest.register_on_joinplayer(function(player)
@ -17,8 +18,8 @@ end)
--manages fatigue and sleeping
function update_energy()
energy_timer = energy_timer + 1
if energy_timer >= 200 then
fatigue_timer = fatigue_timer + 1
if fatigue_timer >= 300 then
for name, energy_level in pairs(energy_levels) do
local player = minetest.get_player_by_name(name)
if energy_levels[name] > 0 and player:get_hp() > 0 then
@ -28,6 +29,11 @@ function update_energy()
end
update_energy_hud(name)
end
fatigue_timer = 0
end
sleep_timer = sleep_timer + 1
if sleep_timer >= 100 then
for name, pos in pairs(sleeping) do
local player = minetest.get_player_by_name(name)
if energy_levels[name] ~= nil then
@ -36,10 +42,10 @@ function update_energy()
end
end
update_energy_hud(name)
end
energy_timer = 0
end
sleep_timer = 0
end
for name, pos in pairs(sleeping) do
local player = minetest.get_player_by_name(name)
if energy_levels[name] ~= nil then

View File

@ -1,18 +1,15 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--
local text_list = {"\n\nYou are a prospector on a newly discovered moon.\n" ..
"Your habitat has been constructed and your mining systems are operational.\n" ..
"Your habitat has been constructed and your mining systems are operational.\n\n" ..
"As a resident engineer, you must manage life support systems and\n" ..
"mining equipment to ensure your income is adequate for survival.\n\n" ..
"Expenses are deducted from your balance at regular intervals.\n" ..
"The amount deducted increases as time goes on, increasing the difficulty of the game.\n\n" ..
"You can win the game by earning $30,000 and lose if you reach $10,000 in debt.\n" ..
"These limits can be removed with the /unlimited console command.\n" ..
"You must be granted server privileges to use this command, (ie: /grantme server)\n",
"Expenses are deducted from your balance at regular intervals and\n" ..
"are increased based on the total amount of ore you have mined.",
"\n\n\n\n This is your nuclear reactor, the power source for your habitat.\n" ..
" Left click the reactor to turn it on or off.\n\n If the reactor is overloaded" ..
@ -77,7 +74,23 @@ local text_list = {"\n\nYou are a prospector on a newly discovered moon.\n" ..
"\n\n\n\nThis is your research station. Here, you can conduct research on organic matter\n" ..
"'harvested' on the moon's surface. Organic matter is worth $10 each early in the game.\n" ..
"This value increase each time you process research data. The limit is $50.\n" ..
"To conduct research, left click the research station while holding the organic matter."
"To conduct research, left click the research station while holding the organic matter.",
"\n\n\n\nThis is an auto-restart circuit. A sensor is placed directly next to the machine.\n" ..
"A relay is placed directly next to the sensor. From there, wire is used to connect\n" ..
"the relay to a microcontroller programmed to operate as a NOT gate.\n" ..
"Wire is then ran through a delayer back to the machine. This will restart a machine\n" ..
"if it fails but will not do so after a power outage.",
"\n\n\n\nThese are reactor boosters. Boosters increase reactor output by 100 each.\n" ..
"They must be placed within 20 meters of the reactor and cannot be ran continuously.\n" ..
"After 10 seconds, they will overload the reactor. When disabled, the booster has a\n" ..
"10 second cooldown. Boosters can be operated by pulsing logic circuits or 'clocks'.\n" ..
"The best way to configure boosters is to stagger circuits so one group is on while\n" ..
"the other is off. This way your reactor output has a steady value.",
"\n\n\n\n\n\nThis is the habitat computer. Here you can view the result of the current\n" ..
"drill and coolant pump settings as well as gravity's affect on machine stability."
}
local index = 1
@ -97,8 +110,9 @@ function inventory_formspec(player)
"size[8,7.5]",
"bgcolor[#2d2d2d;false]",
"list[current_player;main;0,3.5;8,4;]",
"button[3,0.9;2,0.5;Help;Help]",
"button[3,1.9;2,0.5;Shop;Shop]"
"button[3,0.4;2,0.5;Tutorial;Tutorial]",
"button[3,1.4;2,0.5;Manual;Manual]",
"button[3,2.4;2,0.5;Shop;Shop]"
}
return formspec
end
@ -110,7 +124,7 @@ function help_formspec(player)
"bgcolor[#2d2d2d;false]",
"image[-1,-1;40,28;"..border.."]",
"image[5.5,0.5;24,13.5;"..image.."]",
"label[9,12;"..text.."]",
"label[8.5,12;"..text.."]",
"button[11.5,18;3,0.75;<-;<-]",
"button[15.5,18;3,0.75;->;->]",
"button[13.5,20;3,0.75;Back;Back]"
@ -132,6 +146,13 @@ end
function computer_formspec()
local drill_active = bool_to_number(drill_on())
local gravity_active = bool_to_number(gravity_on())
local ds = drill_speed > 2000 and 2000 or drill_speed
local dr = drill_resistance > 2000 and 2000 or drill_resistance
local dc = drill_cooling > 2000 and 2000 or drill_cooling
local dd = drill_digging > 2000 and 2000 or drill_digging
local dp = drill_power > 2000 and 2000 or drill_power
local gg = generated_gravity > 100 and 100 or generated_gravity
local sb = stability > 100 and 100 or stability
local on_formspec = {
"size[30,22]",
"bgcolor[#2d2d2d;false]",
@ -143,16 +164,16 @@ function computer_formspec()
"label[3,13.15;Cooling: ]",
"label[3,15.15;Production: ]",
"label[3,17.15;Electrical load: ]",
"image[6,9;" .. drill_active * drill_speed * 0.01 .. ",1;"..green.."]",
"image[6,11;" .. drill_resistance * 0.005 .. ",1;"..red.."]",
"image[6,13;" .. drill_cooling * 0.005 .. ",1;"..blue.."]",
"image[6,15;" .. drill_digging * 0.005 .. ",1;"..green.."]",
"image[6,17;" .. drill_power * 0.01 .. ",1;"..red.."]",
"image[6,9;" .. drill_active * ds * 0.005 .. ",1;"..green.."]",
"image[6,11;" .. dr * 0.005 .. ",1;"..red.."]",
"image[6,13;" .. dc * 0.005 .. ",1;"..blue.."]",
"image[6,15;" .. dd * 0.005 .. ",1;"..green.."]",
"image[6,17;" .. dp * 0.005 .. ",1;"..red.."]",
"label[20.65,1;Gravity Generator]",
"image[20.25,2;4.824,6.633;"..computer_gravity.."]",
"label[19,9.15;Intensity: ]",
"image[22,9;" .. gravity_active * generated_gravity * 0.05 .. ",1;"..green.."]",
"image[22,11;" .. stability * 0.05 .. ",1;"..blue.."]",
"image[22,9;" .. gravity_active * gg * 0.05 .. ",1;"..green.."]",
"image[22,11;" .. sb * 0.05 .. ",1;"..blue.."]",
"label[19,11.15;Habitat stability: ]",
"label[13.5,20;Press escape to exit.]",
}
@ -185,17 +206,19 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local name = player:get_player_name()
if formname == "" then
for key, val in pairs(fields) do
if key == "Help" then
if key == "Manual" then
local formspec = help_formspec(player)
player:set_inventory_formspec(table.concat(formspec, ""))
elseif key == "Shop" then
local formspec = shop_formspec(player)
player:set_inventory_formspec(table.concat(formspec, ""))
elseif key == "Tutorial" then
start_tutorial(player)
elseif key == "Back" then
local formspec = inventory_formspec(player)
player:set_inventory_formspec(table.concat(formspec, ""))
elseif key == "->" then
if index < 12 then
if index < 15 then
index = index + 1
else
index = 1
@ -208,7 +231,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if index > 1 then
index = index - 1
else
index = 12
index = 15
end
text = text_list[index]
image = "readme__" .. index .. ".png"

View File

@ -1,11 +1,11 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "structure.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "rooms.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "structure.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "rooms.lua")
habitat_built = false
pump_pos = vector.new(-4, 1, -20)

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--
@ -445,6 +445,12 @@ function update_money_hud()
text = "Money: $" .. money,
number = 0xFFFFFF
})
local spec = player:get_inventory_formspec()
local str = string.sub(spec,48,51)
if str == "Shop" then
local formspec = shop_formspec(player)
player:set_inventory_formspec(table.concat(formspec, ""))
end
end
end
end

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--
@ -57,7 +57,7 @@ minetest.register_craftitem("moontest:space_food", {
--manages hunger for all players
function update_hunger()
hunger_timer = hunger_timer + 1
if hunger_timer >= 200 then
if hunger_timer >= 150 then
for name, hunger_level in pairs(hunger_levels) do
local player = minetest.get_player_by_name(name)
if hunger_levels[name] > 0 and player:get_hp() > 0 then

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--
@ -61,12 +61,14 @@ minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing)
minetest.set_node(oxygen_generator_pos, {name = "moontest:oxygen_generator_off"})
add_hud_message("Oxygen generator: off")
elseif node.name == "moontest:oxygen_generator_collider" and oxygen_on() == false and power_on() then
minetest.sound_play('oxygen_start_stop', {
pos = oxygen_generator_pos,
max_hear_distance = 16
})
minetest.set_node(oxygen_generator_pos, {name = "moontest:oxygen_generator_on"})
add_hud_message("Oxygen generator: on")
if tutorial_active == false or tutorial_step ~= 13 then
minetest.sound_play('oxygen_start_stop', {
pos = oxygen_generator_pos,
max_hear_distance = 16
})
minetest.set_node(oxygen_generator_pos, {name = "moontest:oxygen_generator_on"})
add_hud_message("Oxygen generator: on")
end
end
if node.name == "moontest:gravity_generator_collider" and gravity_on() then

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--

View File

@ -1,15 +1,15 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--
--all standard nodes are registered here, other nodes are handled by the scripts below
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "machine_nodes.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "pipe_nodes.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "special_nodes.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "code" .. DIR_DELIM .. "colliders.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "machine_nodes.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "pipe_nodes.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "special_nodes.lua")
dofile(minetest.get_modpath("moontest") .. DIR_DELIM .. "src" .. DIR_DELIM .. "colliders.lua")
minetest.register_node("moontest:moon_surface", {
name = "moon_surface",

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--
@ -30,7 +30,7 @@ minetest.register_node("moontest:reactor_booster", {
effector = {
action_on = function(pos, node)
local meta = minetest.get_meta(pos)
if vector.distance(pos, reactor_pos) < 20 then
if vector.distance(pos, reactor_pos) < 10 then
if meta:get_int("on") == 0 then
max_power = max_power + 100
meta:set_int("on", 1)

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--

View File

@ -1,7 +1,7 @@
--[[
Shop Menu
Author: Droog71
License: AGPLv3
Moon Habitat Simulator
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--
local index = 1
@ -10,36 +10,39 @@ local item_btn_keys = {}
local loaded = false
local items_for_sale = {
["wire"] = "mesecons:wire_00000000_off",
["switch"] = "mesecons_switch:mesecon_switch_off",
["noteblock"] = "mesecons_noteblock:noteblock",
["button"] = "mesecons_button:button_off",
["delayer"] = "mesecons_delayer:delayer_off_1",
["controller"] = "mesecons_microcontroller:microcontroller0000",
["sensor"] = "moontest:sensor",
["relay"] = "moontest:relay_off",
["reactor_booster"] = "moontest:reactor_booster"
["Wire"] = "mesecons:wire_00000000_off",
["Switch"] = "mesecons_switch:mesecon_switch_off",
["Note Block"] = "mesecons_noteblock:noteblock",
["Button"] = "mesecons_button:button_off",
["Delayer"] = "mesecons_delayer:delayer_off_1",
["Microcontroller"] = "mesecons_microcontroller:microcontroller0000",
["Sensor"] = "moontest:sensor",
["Relay"] = "moontest:relay_off",
["Reactor Booster"] = "moontest:reactor_booster"
}
local item_prices = {
["wire"] = 10,
["switch"] = 20,
["noteblock"] = 10,
["button"] = 20,
["delayer"] = 100,
["controller"] = 250,
["sensor"] = 250,
["relay"] = 250,
["reactor_booster"] = 500
["Wire"] = 10,
["Switch"] = 20,
["Note Block"] = 10,
["Button"] = 20,
["Delayer"] = 100,
["Microcontroller"] = 250,
["Sensor"] = 250,
["Relay"] = 250,
["Reactor Booster"] = 500
}
minetest.register_on_joinplayer(function(player)
if loaded == false then
for item_name,item in pairs(items_for_sale) do
local stack = ItemStack(item)
item_buttons[index] = "button[3," ..
index .. ";4,2;" .. item_name ..
";" .. item_name .. "]" ..
"item_image[7," .. index + 0.6 ..
";0.6,0.6;" .. item .. "]" ..
"tooltip[" .. item_name .. ";" ..
stack:get_description() .. ";#353535;#FFFFFF]" ..
"label[8," .. index + 0.6 .. ";" .. " $" ..
item_prices[item_name] .."]"
item_btn_keys[item_name] = item
@ -54,6 +57,7 @@ function shop_formspec(player)
local formspec = {
"size[10,16]",
"bgcolor[#353535;false]",
"label[4.5,0.5;Shop]",
table.concat(item_buttons),
"label[3.5,11.5;".."Your balance: $" .. money.."]",
"button[3,13;4,2;Back;Back]"

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--
@ -28,7 +28,7 @@ minetest.register_globalstep(function(dtime)
if energy_levels[name] > 0 then
player:set_physics_override({speed = 1.8})
energy_timers[name] = energy_timers[name] + 1
if energy_timers[name] >= 100 then
if energy_timers[name] >= 150 then
energy_levels[name] = energy_levels[name] - 1
energy_timers[name] = 0
update_energy_hud(name)

View File

@ -1,6 +1,6 @@
--[[
Moon Habitat Simulator
Version: 1.0.2
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--

View File

@ -0,0 +1,466 @@
--[[
Moon Habitat Simulator
Version: 1.0.3
License: GNU Affero General Public License version 3 (AGPLv3)
]]--
tutorial_active = false
tutorial_step = 1
local hud_img = nil
local tutorial_timer = 0
local current_fs_string = 1
local tutorial_step_complete = 1
local tutorial_fs_strings = {
"size[8,8]" ..
"bgcolor[#2d2d2d;false]" ..
"label[1.5,0.5;" .. "Welcome to the moon habitat simulator!\n\n" ..
"The first step of this tutorial is about food.\n" ..
"You will need to eat to survive on the moon.\n" ..
"Make your way to the space food vending machine\n" ..
"in the habitat and buy some food.\n\n" .. "]" ..
"image[1.5,3.5;6,3.375;readme__10.png]" ..
"button[3,7;2,0.5;ok;OK]",
"size[8,6]" ..
"bgcolor[#2d2d2d;false]" ..
"label[1.5,0.5;" .. "Well done!\n\n" ..
"Left click with the food in your hand to eat.\n" ..
"This will reduce your hunger. Pay close attention to\n" ..
"the hunger variable on the left side of the screen.\n" ..
"Next, we will talk about sleep.\n\n" .. "]" ..
"button[3,4.5;2,0.5;next;Next]",
"size[8,8]" ..
"bgcolor[#2d2d2d;false]" ..
"label[1.5,0.5;" .. "Your energy is displayed on the\n" ..
"left side of the screen. If this gets too low,\n" ..
"you will die. You will need sleep to survive.\n" ..
"Make your way to the sleeping quarters and click\n" ..
"on the bottom bunk of a bunk bed to sleep.\n\n" .. "]" ..
"image[1.5,3.5;6,3.375;readme__11.png]" ..
"button[3,7;2,0.5;ok;OK]",
"size[8,11]" ..
"bgcolor[#2d2d2d;false]" ..
"label[1.5,1;" .. "This is your hvac system. Without it,\n" ..
"you cannot survive. Left click the box on top to turn\n" ..
"it on or off. Right click the box to adjust the thermostat.\n\n" ..
"The hvac system's power consumption is dependent on the\n" ..
"thermostat setting. Lower values allow you to divert power\n" ..
"elsewhere. Higher values provide more safety.\n" ..
"Extremely high thermostat settings can be dangerous.\n" ..
"This machine is not helpful when the airlock is open.\n" ..
"Go ahead and try adjusting the thermostat now.]" ..
"image[1.5,6;6,3.375;readme__6.png]" ..
"button[3,10;2,0.5;ok;OK]",
"size[8,11]" ..
"bgcolor[#2d2d2d;false]" ..
"label[1.5,1;" .. "This is your oxygen generator. Without it,\n" ..
"you cannot survive. Left click the generator to turn\n" ..
"it on or off. Right click the generator to adjust the output.\n\n" ..
"This machine's power consumption is dependent on the\n" ..
"output setting. Lower values allow you to divert power\n" ..
"elsewhere. Higher values provide more safety.\n" ..
"Extremely high output settings can be dangerous.\n" ..
"This machine is not helpful when the airlock is open.\n" ..
"Go ahead and try adjusting the output now.]" ..
"image[1.5,6;6,3.375;readme__5.png]" ..
"button[3,10;2,0.5;ok;OK]",
"size[8,11]" ..
"bgcolor[#2d2d2d;false]" ..
"label[1.5,1;" .. "This is your gravity generator.\nWithout it, " ..
"other machines become unstable.\nLeft click the generator to turn " ..
"it on or off.\nRight click the generator to adjust the intensity.\n\n" ..
"This machine's power consumption is dependent on the\n" ..
"intensity setting. Lower values allow you to divert power\n" ..
"elsewhere. Higher values provide more stability but values\n" ..
"over 100 will cause your machines to become unstable.\n" ..
"Go ahead and try adjusting the output now.]" ..
"image[1.5,6;6,3.375;readme__4.png]" ..
"button[3,10;2,0.5;ok;OK]",
"size[8,9]" ..
"bgcolor[#2d2d2d;false]" ..
"label[1.5,1;" ..
"This is your nuclear reactor.\n" ..
"The power source for your habitat.\n" ..
"Left click the reactor to turn it on or off.\n" ..
"If the reactor is overloaded or you turn it off,\n" ..
"all of your equipment will have to be restarted.]" ..
"image[1.5,4;6,3.375;readme__2.png]" ..
"button[3,8;2,0.5;next;Next]",
"size[8,11]" ..
"bgcolor[#2d2d2d;false]" ..
"label[1.5,1;" ..
"This is your mining drill.\n" ..
"Your primary source of passive income.\n" ..
"Left click the drill to turn it on or off.\n" ..
"Right click the drill to adjust the it's speed.\n" ..
"Power consumption is dependent on the speed setting.\n" ..
"When changed, you must also adjust the coolant pump.\n" ..
"Otherwise, you will experience fluctuations in power\n" ..
"consumption and may overload your reactor.\n" ..
"Go ahead and try adjusting the drill speed now.]" ..
"image[1.5,6;6,3.375;readme__7.png]" ..
"button[3,10;2,0.5;ok;OK]",
"size[8,9]" ..
"bgcolor[#2d2d2d;false]" ..
"label[1.5,1;" ..
"This is your coolant system which prevents\n" ..
"the mining drill from overloading the reactor.\n" ..
"Left click the pump to turn it on or off.\n" ..
"Right click the pump to adjust it's speed.\n" ..
"Power consumption is dependent on the speed setting.\n" ..
"Go ahead and try adjusting the pump speed now.]" ..
"image[1.5,4;6,3.375;readme__8.png]" ..
"button[3,8;2,0.5;ok;OK]",
"size[8,9]" ..
"bgcolor[#2d2d2d;false]" ..
"label[1.5,1;" ..
"This is the habitat computer.\n" ..
"Here you can view the result of the current\n" ..
"drill and coolant pump settings, as well as\n" ..
"the gravity generator's affect on machine stability.]" ..
"image[1.5,4;6,3.375;readme__15.png]" ..
"button[3,8;2,0.5;next;Next]",
"size[8,9]" ..
"bgcolor[#2d2d2d;false]" ..
"label[1.5,1;" ..
"This is your research station.\n" ..
"Here you can exchange mob drops for money.\n" ..
"Left click the research station with the\n" ..
"green goo in your hand to continue.]" ..
"image[1.5,4;6,3.375;readme__12.png]" ..
"button[3,8;2,0.5;ok;OK]",
"size[8,11]" ..
"bgcolor[#2d2d2d;false]" ..
"label[1.5,1;" ..
"This is an auto-restart circuit.\n" ..
"A sensor is placed directly next to the machine.\n" ..
"A relay is placed directly next to the sensor.\n" ..
"From there, wire is used to connect the relay to\n" ..
"a microcontroller programmed to operate as a NOT gate.\n" ..
"Wire is then ran through a delayer back to the machine.\n" ..
"This will restart a machine if it fails\n" ..
"but will not do so after a power outage.\n" ..
"Go ahead and try building one of these\n" ..
"for your oxygen generator now.]" ..
"image[1.5,6;6,3.375;readme__13.png]" ..
"button[3,10;2,0.5;ok;OK]",
"size[8,11]" ..
"bgcolor[#2d2d2d;false]" ..
"label[1.5,1;" ..
"These are reactor boosters.\n" ..
"Boosters increase reactor output by 100 each.\n" ..
"They must be placed within 20 meters of the reactor.\n" ..
"Boosters cannot be ran continuously.\n" ..
"After 10 seconds, they will overload the reactor.\n" ..
"When disabled, the booster has a 10 second cooldown.\n" ..
"Boosters can be operated by pulsing logic or 'clocks'.\n" ..
"The best way to configure boosters is to stagger\n" ..
"circuits so one group is on while the other is off.\n" ..
"This way your reactor output has a steady value.\n" ..
"Go ahead and try setting one of these up now.]" ..
"image[1.5,6;6,3.375;readme__14.png]" ..
"button[3,10;2,0.5;ok;OK]",
"size[6,4]" ..
"bgcolor[#2d2d2d;false]" ..
"label[1,0.5;" .. "Congratulations!\n\n" ..
"You have completed the tutorial.\n" ..
"Click ok to resume normal gameplay.]" ..
"button[2,3;2,0.5;ok;OK]"
}
--gets the size of a table
local function get_size(table)
local size = 0
for k,v in pairs(table) do
size = size + 1
end
return size
end
--empties the inventory
local function empty_inventory(player)
local inv = player:get_inventory()
for name, list in pairs(inv:get_lists()) do
inv:set_list(name, {})
end
end
--restarts the game
local function restart_game()
money = 1000
max_power = 600
thermostat = 100
oxygen_output = 100
drill_speed = 100
pump_speed = 100
generated_gravity = 100
aggro = 0.3
research_progress = 1
expense_timer = 0
for index, alien in pairs(aliens) do
alien:remove()
aliens[index] = nil
end
alien_count = 0
build_habitat()
gravity_failed = false
airlock_failed = false
oxygen_failed = false
hvac_failed = false
drill_failed = false
pump_failed = false
update_airlock_hud()
update_gravity_hud()
update_oxygen_output_hud()
update_thermostat_hud()
update_drill_hud()
update_coolant_hud()
update_money_hud()
update_message_hud()
for _,player in pairs(minetest.get_connected_players()) do
local player_name = player:get_player_name()
oxygen_levels[player_name] = 100
hunger_levels[player_name] = 100
energy_levels[player_name] = 100
temperature_levels[player_name] = 100
update_energy_hud(player_name)
update_hunger_hud(player_name)
update_oxygen_hud(player_name)
update_temperature_hud(player_name)
empty_inventory(player)
player:set_hp(20)
player:set_pos(vector.new(0, 1, 5))
end
end
--defines the warning formspec
local function warning_formspec(player)
local name = player:get_player_name()
local formspec = {
"size[9,4]",
"bgcolor[#2d2d2d;false]",
"label[1.5,1;Starting the tutorial will interrupt any progress you have made!\n" ..
"Are you sure you want to continue?]",
"button_exit[5,3;2,0.5;start;Continue]",
"button_exit[2,3;2,0.5;cancel;Cancel]"
}
return formspec
end
--defines the denied formspec
local function denied_formspec(player)
local name = player:get_player_name()
local formspec = {
"size[8.5,4]",
"bgcolor[#2d2d2d;false]",
"label[2,1;The tutorial is only available in single player.]",
"button_exit[3,3;2,0.5;OK;OK]"
}
return formspec
end
--checks if the current tutorial step has been completed
local function check_tutorial_conditions(player)
local name = player:get_player_name()
if tutorial_step == 2 and tutorial_step_complete == 1 then
if player:get_inventory():contains_item("main", "moontest:space_food") then
tutorial_step_complete = tutorial_step_complete + 1
end
elseif tutorial_step == 4 and tutorial_step_complete == 3 then
if is_sleeping(name) then
wake_up(player, name)
tutorial_step_complete = tutorial_step_complete + 1
end
elseif tutorial_step == 5 and tutorial_step_complete == 4 then
if thermostat ~= 100 then
tutorial_step_complete = tutorial_step_complete + 1
end
elseif tutorial_step == 6 and tutorial_step_complete == 5 then
if oxygen_output ~= 100 then
tutorial_step_complete = tutorial_step_complete + 1
end
elseif tutorial_step == 7 and tutorial_step_complete == 6 then
if generated_gravity ~= 100 then
tutorial_step_complete = tutorial_step_complete + 1
end
elseif tutorial_step == 9 and tutorial_step_complete == 8 then
if drill_speed ~= 100 then
tutorial_step_complete = tutorial_step_complete + 1
end
elseif tutorial_step == 10 and tutorial_step_complete == 9 then
if pump_speed ~= 100 then
tutorial_step_complete = tutorial_step_complete + 1
end
elseif tutorial_step == 11 and tutorial_step_complete == 11 then
if not player:get_inventory():contains_item("main", "moontest:splat") then
local stack = ItemStack("moontest:splat")
stack:set_count(50)
player:get_inventory():add_item("main", stack)
end
elseif tutorial_step == 12 and tutorial_step_complete == 11 then
if research_progress ~= 1 then
tutorial_step_complete = tutorial_step_complete + 1
end
elseif tutorial_step == 12 and tutorial_step_complete == 12 then
if not player:get_inventory():contains_item("main", "moontest:sensor") then
local stack1 = ItemStack("moontest:sensor")
stack1:set_count(10)
player:get_inventory():add_item("main", stack1)
local stack2 = ItemStack("moontest:relay_off")
stack2:set_count(10)
player:get_inventory():add_item("main", stack2)
local stack3 = ItemStack("mesecons_delayer:delayer_off_1")
stack3:set_count(10)
player:get_inventory():add_item("main", stack3)
local stack4 = ItemStack("mesecons_microcontroller:microcontroller0000")
stack4:set_count(10)
player:get_inventory():add_item("main", stack4)
local stack5 = ItemStack("mesecons:wire_00000000_off")
stack5:set_count(50)
player:get_inventory():add_item("main", stack5)
minetest.set_node(oxygen_generator_pos, {name = "moontest:oxygen_generator_off"})
hud_img = player:hud_add({
hud_elem_type = "image",
position = {x = 0.5, y = 0.15},
offset = {x = 0, y = 0},
scale = {x = 0.25, y = 0.25},
text = "readme__13.png"
})
end
elseif tutorial_step == 13 and tutorial_step_complete == 12 then
if minetest.get_node(oxygen_generator_pos).name == "moontest:oxygen_generator_on" then
player:hud_remove(hud_img)
tutorial_step_complete = tutorial_step_complete + 1
end
elseif tutorial_step == 13 and tutorial_step_complete == 13 then
if not player:get_inventory():contains_item("main", "moontest:reactor_booster") then
local stack1 = ItemStack("moontest:reactor_booster")
stack1:set_count(10)
player:get_inventory():add_item("main", stack1)
local stack2 = ItemStack("mesecons_button:button_off")
stack2:set_count(10)
player:get_inventory():add_item("main", stack2)
hud_img = player:hud_add({
hud_elem_type = "image",
position = {x = 0.5, y = 0.15},
offset = {x = 0, y = 0},
scale = {x = 0.25, y = 0.25},
text = "readme__14.png"
})
end
elseif tutorial_step == 14 and tutorial_step_complete == 13 then
if max_power > 600 then
tutorial_step_complete = tutorial_step_complete + 1
player:hud_remove(hud_img)
end
elseif tutorial_step == 15 and tutorial_step_complete == 14 then
empty_inventory(player)
player:set_physics_override({gravity = 0})
for x = -24, 24, 1 do
for z = -24, 24, 1 do
for y = 0, 8, 1 do
minetest.remove_node(vector.new(x, y, z))
end
end
end
restart_game()
tutorial_active = false
end
end
--starts the tutorial in singleplayer or shows a denial message in multiplayer
function start_tutorial(player)
local name = player:get_player_name()
if get_size(minetest.get_connected_players()) < 2 then
minetest.show_formspec(name,"warning",table.concat(warning_formspec(player)))
else
minetest.show_formspec(name,"denied",table.concat(denied_formspec(player)))
end
end
--prevents cheating by exiting the game with free tutorial items
minetest.register_on_shutdown(function()
if tutorial_active then
for _,player in pairs(minetest.get_connected_players()) do
empty_inventory(player)
end
for x = -24, 24, 1 do
for z = -24, 24, 1 do
for y = 0, 8, 1 do
minetest.remove_node(vector.new(x, y, z))
end
end
end
restart_game()
end
end)
--updates the tutorial formspecs and completion status
minetest.register_globalstep(function(dtime)
if tutorial_active == true then
tutorial_timer = tutorial_timer + 1
if tutorial_timer > 10 then
for _,player in pairs(minetest.get_connected_players()) do
local name = player:get_player_name()
if tutorial_step_complete == tutorial_step then
if tutorial_step <= get_size(tutorial_fs_strings) then
current_fs_string = tutorial_fs_strings[tutorial_step]
minetest.show_formspec(name,"tutorial", current_fs_string)
end
end
energy_levels[name] = 75
update_gravity(name)
check_tutorial_conditions(player)
end
tutorial_timer = 0
end
end
end)
--handles all button clicks
minetest.register_on_player_receive_fields(function(player, formname, fields)
local name = player:get_player_name()
if formname == "tutorial" then
for key, val in pairs(fields) do
if key == "ok" then
minetest.close_formspec(name, "tutorial")
tutorial_step = tutorial_step + 1
end
if key == "next" then
minetest.close_formspec(name, "tutorial")
tutorial_step = tutorial_step + 1
tutorial_step_complete = tutorial_step_complete + 1
end
end
end
if formname == "warning" then
for key, val in pairs(fields) do
if key == "start" then
tutorial_step = 1
tutorial_step_complete = 1
tutorial_active = true
restart_game()
end
end
end
end)

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 960 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 809 KiB