You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
412 lines
16 KiB
412 lines
16 KiB
local Lifesupport = {}
|
|
--[[
|
|
Lifesupport mechanics:
|
|
Consume lifesupport canisters for food & air
|
|
|
|
Equiment boosts the lifesupport drain efficiency, stacks additivly.
|
|
All thruster suits have some base level life support efficiency, 1 module is built-in.
|
|
|
|
Non-thruster suits can have modules added but only function on land and efficiency banafits are halved. Only useful on hostile planets.
|
|
A spacesuit proper spacesuit is required in space.
|
|
|
|
]]
|
|
|
|
Lifesupport.name_gui_root = mod_prefix.."lifesupport"
|
|
Lifesupport.name_window_close = "close_lifesupport"
|
|
Lifesupport.name_sound_used_canister = mod_prefix .. "canister-breath"
|
|
|
|
Lifesupport.lifesupport_refil_threshold = 50
|
|
Lifesupport.lifesupport_bar_max = 150
|
|
Lifesupport.lifesupport_per_second = 1 -- at 100% hazard (space)
|
|
Lifesupport.tick_interval = 240
|
|
Lifesupport.check_inventory_interval = Lifesupport.tick_interval * 4
|
|
|
|
Lifesupport.min_effective_efficiency = 0.25 -- acts as damage multiplier
|
|
Lifesupport.spacesuit_base_efficiency = 1
|
|
Lifesupport.non_spacesuit_base_efficiency = 0
|
|
Lifesupport.non_spacesuit_efficiency_multiplier = 0.5
|
|
|
|
Lifesupport.lifesupport_canisters = {
|
|
{
|
|
name = mod_prefix .. "lifesupport-canister",
|
|
used = mod_prefix .. "used-lifesupport-canister",
|
|
lifesupport = 100
|
|
}
|
|
}
|
|
|
|
Lifesupport.lifesupport_equipment = {
|
|
[mod_prefix .. "lifesupport-equipment-1"] = {efficiency = 1},
|
|
[mod_prefix .. "lifesupport-equipment-2"] = {efficiency = 2},
|
|
[mod_prefix .. "lifesupport-equipment-3"] = {efficiency = 4},
|
|
[mod_prefix .. "lifesupport-equipment-4"] = {efficiency = 8},
|
|
}
|
|
|
|
--[[
|
|
playerdata.user_opened_armor_gui -> flag that says user has armor gui open and we show life support gui
|
|
playerdata.environment_hostile -> flag for hostile environment where air is used up
|
|
playerdata.suit_thrust_bonused -> flag for thruster suit giving bonuses to thrusters
|
|
]]
|
|
|
|
function Lifesupport.get_gui(player)
|
|
return player.gui.left[Lifesupport.name_gui_root]
|
|
end
|
|
|
|
function Lifesupport.check_inventory_reserve_lifesupport(player)
|
|
local playerdata = get_make_playerdata(player)
|
|
local character = player_get_character(player)
|
|
if not character then
|
|
playerdata.reserve_lifesupport = 0
|
|
return
|
|
end
|
|
playerdata.reserve_lifesupport = 0
|
|
local inventory = character.get_main_inventory()
|
|
if inventory and inventory.valid then
|
|
for _, lifesupport_canister in pairs(Lifesupport.lifesupport_canisters) do
|
|
playerdata.reserve_lifesupport = playerdata.reserve_lifesupport + inventory.get_item_count(lifesupport_canister.name) * lifesupport_canister.lifesupport
|
|
end
|
|
end
|
|
end
|
|
|
|
function Lifesupport.get_current_hazard(player)
|
|
local playerdata = get_make_playerdata(player)
|
|
local character = player_get_character(player)
|
|
if not character then
|
|
playerdata.lifesupport_environment = "unknown"
|
|
return 0
|
|
end
|
|
local position = Util.position_to_tile(character.position)
|
|
local zone = Zone.from_surface(character.surface)
|
|
local spaceship = (zone and zone.type == "spaceship") and zone or nil
|
|
|
|
local hazard = 0
|
|
if character.vehicle then
|
|
hazard = 0
|
|
else
|
|
if not zone then
|
|
-- vaults?
|
|
hazard = 0
|
|
playerdata.lifesupport_environment = "unknown"
|
|
elseif spaceship then
|
|
if spaceship.known_tiles
|
|
and spaceship.known_tiles[position.x] and spaceship.known_tiles[position.x][position.y]
|
|
and (spaceship.known_tiles[position.x][position.y] == Spaceship.tile_status.floor_interior
|
|
or spaceship.known_tiles[position.x][position.y] == Spaceship.tile_status.floor_console_connected
|
|
or spaceship.known_tiles[position.x][position.y] == Spaceship.tile_status.wall_console_connected
|
|
or spaceship.known_tiles[position.x][position.y] == Spaceship.tile_status.bulkhead_console_connected) then
|
|
hazard = 0
|
|
playerdata.lifesupport_environment = "spaceship-interior"
|
|
else
|
|
hazard = 1
|
|
playerdata.lifesupport_environment = "space"
|
|
end
|
|
else
|
|
local tile = character.surface.get_tile(Util.position_to_tile(character.position))
|
|
if tile and tile.valid and Util.table_contains(Spaceship.names_spaceship_floors, tile.name) then
|
|
hazard = 0
|
|
playerdata.lifesupport_environment = "spaceship-interior"
|
|
elseif Zone.is_space(zone) then
|
|
hazard = 1
|
|
playerdata.lifesupport_environment = "space"
|
|
else
|
|
hazard = 0
|
|
if zone.plague_used then
|
|
hazard = 1
|
|
if zone.type == "moon" then
|
|
playerdata.lifesupport_environment = "plague-moon"
|
|
else
|
|
playerdata.lifesupport_environment = "plague-planet"
|
|
end
|
|
else
|
|
-- land
|
|
-- TODO: Get habitability from zone data. hazard factors: desert, hot, cold, uranium, high aux.
|
|
if zone.type == "moon" then
|
|
playerdata.lifesupport_environment = "moon"
|
|
else
|
|
playerdata.lifesupport_environment = "planet"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return hazard
|
|
|
|
end
|
|
|
|
function Lifesupport.update_lifesupport_efficiency(player)
|
|
local character = player_get_character(player)
|
|
if not character then return end
|
|
local playerdata = get_make_playerdata(player)
|
|
|
|
playerdata.lifesupport_efficiency = 0
|
|
playerdata.has_spacesuit = false
|
|
|
|
local armor_inv = character.get_inventory(defines.inventory.character_armor)
|
|
if armor_inv and armor_inv[1] and armor_inv[1].valid_for_read then
|
|
if util.table_contains(name_thruster_suits, armor_inv[1].name) then
|
|
playerdata.lifesupport_efficiency = Lifesupport.spacesuit_base_efficiency
|
|
playerdata.has_spacesuit = true
|
|
end
|
|
|
|
-- get lifesupport equipment modules
|
|
local grid_efficiency = 0
|
|
if character.grid then
|
|
for name, count in pairs(character.grid.get_contents()) do
|
|
if Lifesupport.lifesupport_equipment[name] ~= nil then
|
|
grid_efficiency = grid_efficiency + count * (Lifesupport.lifesupport_equipment[name].efficiency or 0)
|
|
end
|
|
end
|
|
end
|
|
playerdata.lifesupport_efficiency = playerdata.lifesupport_efficiency + grid_efficiency
|
|
end
|
|
|
|
if not playerdata.has_spacesuit then
|
|
playerdata.lifesupport_efficiency = playerdata.lifesupport_efficiency / 2
|
|
end
|
|
|
|
return playerdata.lifesupport_efficiency
|
|
end
|
|
|
|
|
|
function Lifesupport.on_tick(event)
|
|
for _, player in pairs(game.connected_players) do
|
|
if game.tick % Lifesupport.tick_interval == 0 then
|
|
Lifesupport.consume_lifesupport(player)
|
|
end
|
|
if Lifesupport.get_gui(player) then
|
|
Lifesupport.gui_update(player, playerdata)
|
|
end
|
|
end
|
|
end
|
|
Event.addListener(defines.events.on_tick, Lifesupport.on_tick)
|
|
|
|
|
|
function Lifesupport.consume_lifesupport(player)
|
|
local playerdata = get_make_playerdata(player)
|
|
local character = player_get_character(player)
|
|
if not character then return end
|
|
local hazard = Lifesupport.get_current_hazard(player)
|
|
if hazard > 0 then
|
|
--Lifesupport.gui_open(player)
|
|
Lifesupport.update_lifesupport_efficiency(player) -- saves to playerdata.lifesupport_efficiency
|
|
local efficiency = playerdata.lifesupport_efficiency
|
|
if efficiency > 0 and not playerdata.has_spacesuit then
|
|
local zone = Zone.from_surface(character.surface)
|
|
if Zone.is_space(zone) then
|
|
efficiency = 0
|
|
end
|
|
end
|
|
local effective_efficiency = math.max(efficiency, Lifesupport.min_effective_efficiency)
|
|
local hazard_use_rate_per_s = Lifesupport.lifesupport_per_second * Lifesupport.get_current_hazard(player)
|
|
local effective_use_rate_per_s = hazard_use_rate_per_s / effective_efficiency
|
|
local effective_use_per_interval = Lifesupport.tick_interval * effective_use_rate_per_s / 60
|
|
if efficiency > 0 then
|
|
-- consume lifesupport
|
|
playerdata.lifesupport = (playerdata.lifesupport or 0) - effective_use_per_interval
|
|
if playerdata.lifesupport < Lifesupport.lifesupport_refil_threshold then
|
|
Lifesupport.consume_canister(player, playerdata, character)
|
|
end
|
|
if playerdata.lifesupport < 0 then
|
|
Lifesupport.damage_character(player, playerdata, character, -playerdata.lifesupport)
|
|
playerdata.lifesupport = 0
|
|
end
|
|
else
|
|
-- lifesupport is not funcitioning. Even if there is a lifesupport buffer it won't do anything (eg: non-space suit in space.)
|
|
Lifesupport.damage_character(player, playerdata, character, effective_use_per_interval)
|
|
end
|
|
elseif playerdata.lifesupport == nil or playerdata.lifesupport < Lifesupport.lifesupport_refil_threshold then
|
|
Lifesupport.consume_canister(player, playerdata, character)
|
|
end
|
|
end
|
|
|
|
function Lifesupport.consume_canister(player, playerdata, character)
|
|
local inventory = character.get_main_inventory()
|
|
if inventory and inventory.valid then
|
|
for _, lifesupport_canister in pairs(Lifesupport.lifesupport_canisters) do
|
|
local count = inventory.get_item_count(lifesupport_canister.name)
|
|
if count > 0 then
|
|
inventory.remove({name=lifesupport_canister.name, count=1})
|
|
inventory.insert({name=lifesupport_canister.used, count=1})
|
|
playerdata.lifesupport = (playerdata.lifesupport or 0) + lifesupport_canister.lifesupport
|
|
player.play_sound { path = Lifesupport.name_sound_used_canister }
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function Lifesupport.damage_character(player, playerdata, character, damage)
|
|
-- half damage direct to character
|
|
if damage > character.health then
|
|
player.print({"space-exploration.suffocating-warning"}, {r = 1, g = 0, b = 0, a = 0})
|
|
character.die("neutral")
|
|
Lifesupport.gui_close(player)
|
|
return
|
|
end
|
|
|
|
local shield_damage = 0
|
|
if character.grid then
|
|
shield_damage = character.grid.shield
|
|
end
|
|
character.damage(damage + shield_damage, "neutral", "suffocation")
|
|
player.print({"space-exploration.suffocating-warning"}, {r = 1, g = 0, b = 0, a = 0})
|
|
end
|
|
|
|
function Lifesupport.on_equipment_changed(event)
|
|
local player = game.players[event.player_index]
|
|
local character = player_get_character(player)
|
|
if not character then return end
|
|
Lifesupport.update_lifesupport_efficiency(player)
|
|
end
|
|
Event.addListener(defines.events.on_player_placed_equipment, Lifesupport.on_equipment_changed)
|
|
Event.addListener(defines.events.on_player_removed_equipment, Lifesupport.on_equipment_changed)
|
|
|
|
function Lifesupport.on_armor_changed(event)
|
|
local player = game.players[event.player_index]
|
|
local character = player_get_character(player)
|
|
if not character then return end
|
|
Lifesupport.update_lifesupport_efficiency(player)
|
|
local playerdata = get_make_playerdata(player)
|
|
if playerdata.lifesupport_efficiency and playerdata.lifesupport_efficiency > 0 then
|
|
Lifesupport.gui_open(player, playerdata)
|
|
end
|
|
end
|
|
Event.addListener(defines.events.on_player_armor_inventory_changed, Lifesupport.on_armor_changed)
|
|
|
|
function Lifesupport.on_gui_opened(event)
|
|
local player = game.players[event.player_index]
|
|
if event.gui_type == defines.gui_type.item and event.item and event.item.type == "armor" and event.item.grid then
|
|
Lifesupport.update_lifesupport_efficiency(player)
|
|
local character = player_get_character(player)
|
|
if not character then return end
|
|
local playerdata = get_make_playerdata(player)
|
|
if playerdata.lifesupport_efficiency and playerdata.lifesupport_efficiency > 0 then
|
|
Lifesupport.gui_open(player, playerdata)
|
|
end
|
|
end
|
|
end
|
|
Event.addListener(defines.events.on_gui_opened, Lifesupport.on_gui_opened)
|
|
--[[
|
|
function Lifesupport.on_gui_closed(event)
|
|
local player = game.players[event.player_index]
|
|
|
|
if event.gui_type == defines.gui_type.item then
|
|
Lifesupport.gui_close(player, playerdata)
|
|
end
|
|
|
|
end
|
|
Event.addListener(defines.events.on_gui_closed, Lifesupport.on_gui_closed)
|
|
]]--
|
|
|
|
function Lifesupport.gui_open(player)
|
|
if settings.get_player_settings(player)["se-never-show-lifesupport"].value then
|
|
return
|
|
end
|
|
local gui = Lifesupport.get_gui(player)
|
|
if not gui then
|
|
local root = player.gui.left.add{
|
|
type = "frame",
|
|
name = Lifesupport.name_gui_root,
|
|
direction = "vertical",
|
|
}
|
|
|
|
local title_table = root.add{type="table", name="title_table", column_count=2, draw_horizontal_lines=false}
|
|
title_table.style.horizontally_stretchable = true
|
|
title_table.style.column_alignments[1] = "left"
|
|
title_table.style.column_alignments[2] = "right"
|
|
|
|
local title_frame = title_table.add{type="frame", name="title_frame", caption = {"space-exploration.lifesupport_title"}, style="informatron_title_frame"}
|
|
title_frame.style.right_padding = -5
|
|
|
|
local right_flow = title_table.add{type="flow", name="title_flow_right"}
|
|
--local close = right_flow.add{type="button", name=Lifesupport.name_window_close, caption="✖", style="informatron_close_button"}
|
|
local close = right_flow.add{type="sprite-button", name=Lifesupport.name_window_close, sprite = "utility/close_white", style="informatron_close_button"}
|
|
close.style.width = 28
|
|
close.style.height = 28
|
|
|
|
root.add { type = "label", name = "lifesupport_environment" }
|
|
root.add { type = "label", name = "lifesupport_efficiency" }
|
|
local bar = root.add { type = "progressbar", name="lifesupport_bar", size = 100, value = 0, style = "space_platform_progressbar_fuel" }
|
|
bar.style.color = {r=70/255, g=171/255, b=1}
|
|
root.add { type = "label", name = "lifesupport_suit" }
|
|
root.add { type = "label", name = "lifesupport_reserves" }
|
|
bar.style.horizontally_stretchable = true
|
|
end
|
|
end
|
|
|
|
function Lifesupport.gui_close(player)
|
|
local gui = Lifesupport.get_gui(player)
|
|
if gui then gui.destroy() end
|
|
end
|
|
|
|
function Lifesupport.gui_update(player, playerdata)
|
|
local gui = Lifesupport.get_gui(player)
|
|
if not gui then return end
|
|
local character = player_get_character(player)
|
|
if not (gui and character) then Lifesupport.gui_close(player) return end
|
|
|
|
local playerdata = get_make_playerdata(player)
|
|
Lifesupport.check_inventory_reserve_lifesupport(player)
|
|
local hazard = Lifesupport.get_current_hazard(player)
|
|
if not playerdata.lifesupport_efficiency then
|
|
Lifesupport.update_lifesupport_efficiency(player)
|
|
end
|
|
|
|
if playerdata.has_spacesuit then
|
|
gui.lifesupport_efficiency.caption = {"space-exploration.lifesupport_efficiency_spacesuit", math.floor(playerdata.lifesupport_efficiency * 100) .. "%"}
|
|
else
|
|
gui.lifesupport_efficiency.caption = {"space-exploration.lifesupport_efficiency_no_spacesuit", math.floor(playerdata.lifesupport_efficiency * 100).. "%"}
|
|
end
|
|
|
|
gui.lifesupport_bar.value = math.max(0, math.min(Lifesupport.lifesupport_bar_max, (playerdata.lifesupport or 0) / Lifesupport.lifesupport_bar_max))
|
|
|
|
|
|
local efficiency = playerdata.lifesupport_efficiency
|
|
if efficiency > 0 and not playerdata.has_spacesuit then
|
|
local zone = Zone.from_surface(character.surface)
|
|
if zone and Zone.is_space(zone) then
|
|
efficiency = 0
|
|
end
|
|
end
|
|
|
|
local effective_efficiency = math.max(efficiency, Lifesupport.min_effective_efficiency)
|
|
local is_space_estimation = false
|
|
if hazard == 0 then
|
|
hazard = 1
|
|
is_space_estimation = true
|
|
end
|
|
local hazard_use_rate_per_s = Lifesupport.lifesupport_per_second * hazard
|
|
local effective_use_rate_per_s = hazard_use_rate_per_s / effective_efficiency
|
|
|
|
local lifesupport_suit_s = (playerdata.lifesupport or 0) / effective_use_rate_per_s
|
|
local lifesupport_duration = util.seconds_to_clock(lifesupport_suit_s)
|
|
|
|
local lifesupport_reserve_s = (playerdata.reserve_lifesupport or 0) / effective_use_rate_per_s
|
|
local lifesupport_reserve_duration = util.seconds_to_clock(lifesupport_reserve_s)
|
|
|
|
if is_space_estimation then
|
|
gui.lifesupport_suit.caption = { "space-exploration.lifesupport_suit_est", lifesupport_duration }
|
|
gui.lifesupport_reserves.caption = { "space-exploration.lifesupport_reserves_est", lifesupport_reserve_duration }
|
|
else
|
|
gui.lifesupport_suit.caption = { "space-exploration.lifesupport_suit", lifesupport_duration }
|
|
gui.lifesupport_reserves.caption = { "space-exploration.lifesupport_reserves", lifesupport_reserve_duration }
|
|
end
|
|
|
|
gui.lifesupport_environment.caption = { "space-exploration.lifesupport_environment_"..playerdata.lifesupport_environment, canisters_per_hour, reserve_minutes }
|
|
end
|
|
|
|
function Lifesupport.on_gui_click (event)
|
|
if not (event.element and event.element.valid) then return end
|
|
local element = event.element
|
|
local player = game.players[event.player_index]
|
|
|
|
root = gui_element_or_parent(element, Lifesupport.name_gui_root)
|
|
if root then
|
|
if element.name == Lifesupport.name_window_close then
|
|
Lifesupport.gui_close(player)
|
|
end
|
|
end
|
|
end
|
|
Event.addListener(defines.events.on_gui_click, Lifesupport.on_gui_click)
|
|
|
|
|
|
return Lifesupport
|
|
|