437 lines
20 KiB
Lua
437 lines
20 KiB
Lua
-------------------------------------------------------------------------
|
|
-- TO DO
|
|
-------------------------------------------------------------------------
|
|
|
|
-- INCREASE PROFORMANCE
|
|
-- FIX BUGS
|
|
|
|
-------------------------------------------------------------------------
|
|
-- variables
|
|
-------------------------------------------------------------------------
|
|
|
|
-------------------------------------------------------------------------
|
|
-- MAIN FUNCTIONS
|
|
-------------------------------------------------------------------------
|
|
|
|
-- wil set is_setup to false
|
|
local function set_is_setup()
|
|
global.is_setup = false
|
|
end
|
|
|
|
-- returns a table with all the players that have the "show-pollution-visuals" option on
|
|
local function get_players_to_render_for()
|
|
local result = {}
|
|
|
|
for i, player in pairs(game.players) do
|
|
local show_pollution_visuals = player.mod_settings["show-pollution-visuals"].value
|
|
if show_pollution_visuals then
|
|
table.insert(result, player)
|
|
end
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
-- sets up all the variables and populates them with initial values
|
|
local function setup()
|
|
-- clearing all visuals juist incase there are some
|
|
rendering.clear("pollution-visuals")
|
|
|
|
-- defining chunk tables
|
|
global.polluted_chunks = {}
|
|
global.polluted_chunks_i = nil
|
|
global.all_chunks = {}
|
|
global.all_chunks_i = nil
|
|
|
|
-- defining fading sprite tables
|
|
global.sprites_fading_in = {}
|
|
global.sprites_fading_in_i = nil
|
|
global.sprites_fading_out = {}
|
|
global.sprites_fading_out_i = nil
|
|
|
|
--bool for if we need to check all_chunks or just polluted_chunks
|
|
global.is_checking = false
|
|
|
|
--bool for if we need to start fading the sprites
|
|
global.is_fading = false
|
|
|
|
-- bool for checking if the game is setup or not
|
|
global.is_setup = true
|
|
|
|
-- defining the overworld.
|
|
for _, surface in pairs(game.surfaces) do
|
|
--looping through all the chunks on surface
|
|
for chunk in surface.get_chunks() do
|
|
local x = (chunk.x)
|
|
local y = (chunk.y)
|
|
|
|
-- inserting chunk in all_chunks
|
|
global.all_chunks[surface.index..":"..x..":"..y] = {position = {x=x,y=y}, surface=surface.index}
|
|
|
|
-- inserting chunk in polluted_chunks
|
|
local chunk_pollution_level = surface.get_pollution(chunk.area.left_top)
|
|
if chunk_pollution_level > 0 then
|
|
-- if a neighboring chunk has 0 pollution add it to the polluted_chunk table anyway.
|
|
local N = surface.get_pollution({x*32, (y-1)*32})
|
|
local E = surface.get_pollution({(x+1)*32, y*32})
|
|
local S = surface.get_pollution({x*32, (y+1)*32})
|
|
local W = surface.get_pollution({(x-1)*32, y*32})
|
|
local NE = surface.get_pollution({(x+1)*32, (y-1)*32})
|
|
local SE = surface.get_pollution({(x+1)*32, (y+1)*32})
|
|
local SW = surface.get_pollution({(x-1)*32, (y+1)*32})
|
|
local NW = surface.get_pollution({(x-1)*32, (y-1)*32})
|
|
|
|
global.polluted_chunks[surface.index..":"..x..":"..y] = {position = {x=x,y=y}, r_id={}, surface=surface.index}
|
|
if N == 0 then
|
|
global.polluted_chunks[surface.index..":"..x..":"..(y-1)] = {position = {x=x, y=y-1}, r_id={}, surface=surface.index}
|
|
end
|
|
if E == 0 then
|
|
global.polluted_chunks[surface.index..":"..(x+1)..":"..y] = {position = {x=x+1, y=y}, r_id={}, surface=surface.index}
|
|
end
|
|
if S == 0 then
|
|
global.polluted_chunks[surface.index..":"..x..":"..(y+1)] = {position = {x=x, y=y+1}, r_id={}, surface=surface.index}
|
|
end
|
|
if W == 0 then
|
|
global.polluted_chunks[surface.index..":"..(x-1)..":"..y] = {position = {x=x-1, y=y}, r_id={}, surface=surface.index}
|
|
end
|
|
if NE == 0 then
|
|
global.polluted_chunks[surface.index..":"..(x+1)..":"..(y-1)] = {position = {x=x+1,y=y-1}, r_id={}, surface=surface.index}
|
|
end
|
|
if SE == 0 then
|
|
global.polluted_chunks[surface.index..":"..(x+1)..":"..(y+1)] = {position = {x=x+1, y=y+1}, r_id={}, surface=surface.index}
|
|
end
|
|
if SW == 0 then
|
|
global.polluted_chunks[surface.index..":"..(x-1)..":"..(y+1)] = {position = {x=x-1, y=y+1}, r_id={}, surface=surface.index}
|
|
end
|
|
if NW == 0 then
|
|
global.polluted_chunks[surface.index..":"..(x-1)..":"..(y-1)] = {position = {x=x-1, y=y-1}, r_id={}, surface=surface.index}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- will check if chunks are polluted and put them in polluted_chunks if they are
|
|
local function check_all_chunks()
|
|
for i = 1, settings.global["chunks-per-tick-pollution-visuals"].value do
|
|
local index ,chunk_data = next(global.all_chunks, global.all_chunks_i)
|
|
if index == nil then global.all_chunks_i = nil global.is_checking = false break
|
|
else global.all_chunks_i = index end
|
|
|
|
local surface_i = chunk_data.surface
|
|
local surface = game.surfaces[surface_i]
|
|
local x = chunk_data.position.x
|
|
local y = chunk_data.position.y
|
|
local r_id = chunk_data.r_id
|
|
local chunk_pollution_level = surface.get_pollution({x*32,y*32})
|
|
|
|
--inserting chunk into polluted_chunks
|
|
if chunk_pollution_level > 0 then
|
|
local N = surface.get_pollution({x*32, (y-1)*32})
|
|
local E = surface.get_pollution({(x+1)*32, y*32})
|
|
local S = surface.get_pollution({x*32, (y+1)*32})
|
|
local W = surface.get_pollution({(x-1)*32, y*32})
|
|
local NE = surface.get_pollution({(x+1)*32, (y-1)*32})
|
|
local SE = surface.get_pollution({(x+1)*32, (y+1)*32})
|
|
local SW = surface.get_pollution({(x-1)*32, (y+1)*32})
|
|
local NW = surface.get_pollution({(x-1)*32, (y-1)*32})
|
|
|
|
--adding chunk or neighboring chunks to the polluted_chunks table
|
|
if global.polluted_chunks[surface_i..":"..x..":"..y] == nil then
|
|
global.polluted_chunks[surface_i..":"..x..":"..y] = {position = {x=x,y=y}, r_id={}, surface=surface_i}
|
|
end
|
|
if N == 0 and global.polluted_chunks[surface_i..":"..x..":"..(y-1)] == nil and global.all_chunks[surface_i..":"..x..":"..(y-1)] ~= nil then
|
|
global.polluted_chunks[surface_i..":"..x..":"..(y-1)] = {position = {x=x, y=y-1}, r_id={}, surface=surface_i}
|
|
end
|
|
if E == 0 and global.polluted_chunks[surface_i..":"..(x+1)..":"..y] == nil and global.all_chunks[surface_i..":"..(x+1)..":"..y] ~= nil then
|
|
global.polluted_chunks[surface_i..":"..(x+1)..":"..y] = {position = {x=x+1, y=y}, r_id={}, surface=surface_i}
|
|
end
|
|
if S == 0 and global.polluted_chunks[surface_i..":"..x..":"..(y+1)] == nil and global.all_chunks[surface_i..":"..x..":"..(y+1)] ~= nil then
|
|
global.polluted_chunks[surface_i..":"..x..":"..(y+1)] = {position = {x=x, y=y+1}, r_id={}, surface=surface_i}
|
|
end
|
|
if W == 0 and global.polluted_chunks[surface_i..":"..(x-1)..":"..y] == nil and global.all_chunks[surface_i..":"..(x-1)..":"..y] ~= nil then
|
|
global.polluted_chunks[surface_i..":"..(x-1)..":"..y] = {position = {x=x-1, y=y}, r_id={}, surface=surface_i}
|
|
end
|
|
if NE == 0 and global.polluted_chunks[surface_i..":"..(x+1)..":"..(y-1)] == nil and global.all_chunks[surface_i..":"..(x+1)..":"..(y-1)] ~= nil then
|
|
global.polluted_chunks[surface_i..":"..(x+1)..":"..(y-1)] = {position = {x=x+1,y=y-1}, r_id={}, surface=surface_i}
|
|
end
|
|
if SE == 0 and global.polluted_chunks[surface_i..":"..(x+1)..":"..(y+1)] == nil and global.all_chunks[surface_i..":"..(x+1)..":"..(y+1)] ~= nil then
|
|
global.polluted_chunks[surface_i..":"..(x+1)..":"..(y+1)] = {position = {x=x+1, y=y+1}, r_id={}, surface=surface_i}
|
|
end
|
|
if SW == 0 and global.polluted_chunks[surface_i..":"..(x-1)..":"..(y+1)] == nil and global.all_chunks[surface_i..":"..(x-1)..":"..(y+1)] ~= nil then
|
|
global.polluted_chunks[surface_i..":"..(x-1)..":"..(y+1)] = {position = {x=x-1, y=y+1}, r_id={}, surface=surface_i}
|
|
end
|
|
if NW == 0 and global.polluted_chunks[surface_i..":"..(x-1)..":"..(y-1)] == nil and global.all_chunks[surface_i..":"..(x-1)..":"..(y-1)] ~= nil then
|
|
global.polluted_chunks[surface_i..":"..(x-1)..":"..(y-1)] = {position = {x=x-1, y=y-1}, r_id={}, surface=surface_i}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- draws a sprite for a specified chunk
|
|
local function check_polluted_chunk(chunk_data)
|
|
local surface = game.surfaces[chunk_data.surface]
|
|
local x = chunk_data.position.x
|
|
local y = chunk_data.position.y
|
|
local chunk_pollution_level = surface.get_pollution({x*32,y*32})
|
|
local sprite_target = {(x*32)+16, (y*32)+16}
|
|
local remove_chunk = false
|
|
local players = get_players_to_render_for()
|
|
local max_layers = settings.global["layers-pollution-visuals"].value
|
|
local offset = settings.global["x-offset-pollution-visuals"].value
|
|
local a = settings.global["y-intercept-pollution-visuals"].value
|
|
local b = settings.global["base-pollution-visuals"].value
|
|
local r_id = chunk_data.r_id
|
|
|
|
for i = 1, max_layers do
|
|
local level = a*b^i + offset
|
|
local current_sprite = ""
|
|
local next_sprite = ""
|
|
|
|
-- setting the current sprite
|
|
if r_id[i] ~= nil then current_sprite = rendering.get_sprite(r_id[i]) end
|
|
|
|
-- setting the next sprite
|
|
if chunk_pollution_level > level then
|
|
next_sprite = "smog_middle"
|
|
else
|
|
-- variables of neighboring chunks
|
|
local N = surface.get_pollution({x*32, (y-1)*32})
|
|
local E = surface.get_pollution({(x+1)*32, y*32})
|
|
local S = surface.get_pollution({x*32, (y+1)*32})
|
|
local W = surface.get_pollution({(x-1)*32, y*32})
|
|
local NE = surface.get_pollution({(x+1)*32, (y-1)*32})
|
|
local SE = surface.get_pollution({(x+1)*32, (y+1)*32})
|
|
local SW = surface.get_pollution({(x-1)*32, (y+1)*32})
|
|
local NW = surface.get_pollution({(x-1)*32, (y-1)*32})
|
|
|
|
--selecting the right sprite depending on neighboring chunks pollution values
|
|
if (N > level and S > level) or (W > level and E > level) then next_sprite="smog_middle"
|
|
elseif S > level and W <= level and E <= level then next_sprite="smog_top"
|
|
elseif N > level and W <= level and E <= level then next_sprite="smog_bottom"
|
|
elseif (W > level or (NW > level and SW > level)) and (N <= level and S <= level and NE <= level and SE <= level) then next_sprite="smog_left"
|
|
elseif (E > level or (NE > level and SE > level)) and (N <= level and S <= level and NW <= level and SW <= level) then next_sprite="smog_right"
|
|
elseif SW > level and N <= level and NE <= level and E <= level and SE <= level and S <= level and W <= level and NW <= level then next_sprite="smog_corner_left_top"
|
|
elseif SE > level and N <= level and NE <= level and E <= level and SW <= level and S <= level and W <= level and NW <= level then next_sprite="smog_corner_right_top"
|
|
elseif NW > level and N <= level and NE <= level and E <= level and SW <= level and S <= level and W <= level and SE <= level then next_sprite="smog_corner_left_bottom"
|
|
elseif NE > level and E <= level and SE <= level and S <= level and SW <= level and W <= level and NW <= level and N <= level then next_sprite="smog_corner_right_bottom"
|
|
elseif S > level and E > level and W <= level and N <= level and NW <= level then next_sprite="smog_corner_inv_left_top"
|
|
elseif S > level and W > level and E <= level and N <= level and NE <= level then next_sprite="smog_corner_inv_right_top"
|
|
elseif N > level and E > level and W <= level and S <= level and SW <= level then next_sprite="smog_corner_inv_left_bottom"
|
|
elseif N > level and W > level and E <= level and S <= level and SE <= level then next_sprite="smog_corner_inv_right_bottom"
|
|
elseif N == 0 and E == 0 and S == 0 and W == 0 and NE == 0 and NW == 0 and SE == 0 and SW == 0 and chunk_pollution_level == 0 and r_id == {} then
|
|
remove_chunk = true
|
|
end
|
|
end
|
|
|
|
-- marking sprite for fade in/out
|
|
if r_id[i] ~= nil then
|
|
if next_sprite == "" then
|
|
--mark for fade out
|
|
global.sprites_fading_out[r_id[i]] = {tint = {r=1, g=1, b=1, a=1}, position={x=x,y=y}}
|
|
r_id[i] = nil
|
|
elseif next_sprite ~= current_sprite then
|
|
--mark for fade out
|
|
global.sprites_fading_out[r_id[i]] = {tint = {r=1, g=1, b=1, a=1}, position={x=x,y=y}}
|
|
--mark for fade in
|
|
r_id[i] = rendering.draw_sprite{sprite=next_sprite, surface=surface,target=sprite_target, y_scale=2, x_scale=2, tint={r=0, g=0, b=0, a=0}, players=players}
|
|
if #players == 0 then
|
|
rendering.set_visible(r_id[i], false)
|
|
end
|
|
global.sprites_fading_in[r_id[i]] = {tint = {r=0, g=0, b=0, a=0}, position={x=x,y=y}}
|
|
end
|
|
elseif next_sprite ~= "" then
|
|
--mark for fade in
|
|
r_id[i] = rendering.draw_sprite{sprite=next_sprite, surface=surface,target=sprite_target, y_scale=2, x_scale=2, tint={r=0, g=0,b=0, a=0}, players=players}
|
|
if #players == 0 then rendering.set_visible(r_id[i], false) end
|
|
global.sprites_fading_in[r_id[i]] = {tint = {r=0, g=0, b=0, a=0}, position={x=x,y=y}}
|
|
end
|
|
|
|
--update global tables with new values
|
|
global.polluted_chunks[chunk_data.surface..":"..x..":"..y].r_id[i] = r_id[i]
|
|
end
|
|
|
|
-- delete chunk from polluted_chunks
|
|
if remove_chunk then
|
|
global.polluted_chunks[chunk_data.surface..":"..x..":"..y] = nil
|
|
end
|
|
end
|
|
|
|
-- will check every polluted chunk and draw visuals
|
|
local function check_polluted_chunks()
|
|
for i = 1, settings.global["chunks-per-tick-pollution-visuals"].value do
|
|
local index ,chunk_data = next(global.polluted_chunks, global.polluted_chunks_i)
|
|
if index == nil then global.polluted_chunks_i = nil global.is_fading = true break
|
|
else global.polluted_chunks_i = index end
|
|
check_polluted_chunk(chunk_data)
|
|
end
|
|
end
|
|
|
|
-- fade in/out sprites
|
|
local function fade()
|
|
local is_fading_in = true
|
|
local is_fading_out = true
|
|
|
|
for i = 1, 1000 do
|
|
-- fading in
|
|
if is_fading_in and next(global.sprites_fading_in, global.sprites_fading_in_i) ~= nil then
|
|
local r_id, value = next(global.sprites_fading_in, global.sprites_fading_in_i)
|
|
local r = value.tint.r + 0.01
|
|
local g = value.tint.g + 0.01
|
|
local b = value.tint.b + 0.01
|
|
local a = value.tint.a + 0.01
|
|
|
|
local x = value.position.x
|
|
local y = value.position.y
|
|
|
|
if a >= 1 then
|
|
rendering.set_color(r_id, {r=1, g=1,b=1, a=1})
|
|
global.sprites_fading_in[r_id] = nil
|
|
else
|
|
rendering.set_color(r_id, {r=b, g=g,b=b, a=a})
|
|
global.sprites_fading_in[r_id].tint = {r=b, g=g,b=b, a=a}
|
|
end
|
|
global.sprites_fading_in_i = r_id
|
|
else
|
|
is_fading_in = false
|
|
end
|
|
|
|
--fading out
|
|
if is_fading_out and next(global.sprites_fading_out, global.sprites_fading_out_i) ~= nil then
|
|
local r_id, value = next(global.sprites_fading_out, global.sprites_fading_out_i)
|
|
|
|
local r = value.tint.r - 0.01
|
|
local g = value.tint.g - 0.01
|
|
local b = value.tint.b - 0.01
|
|
local a = value.tint.a - 0.01
|
|
|
|
local x = value.position.x
|
|
local y = value.position.y
|
|
|
|
if a <= 0 then
|
|
rendering.set_color(r_id, {r=0, g=0,b=0, a=0})
|
|
global.sprites_fading_out[r_id] = nil
|
|
rendering.destroy(r_id)
|
|
else
|
|
rendering.set_color(r_id, {r=b, g=g,b=b, a=a})
|
|
global.sprites_fading_out[r_id].tint = {r=b, g=g,b=b, a=a}
|
|
end
|
|
global.sprites_fading_out_i = r_id
|
|
else
|
|
is_fading_out = false
|
|
end
|
|
|
|
if is_fading_in == false and is_fading_out == false then
|
|
break
|
|
end
|
|
end
|
|
|
|
if next(global.sprites_fading_in, global.sprites_fading_in_i) == nil then global.sprites_fading_in_i = nil end
|
|
if next(global.sprites_fading_out, global.sprites_fading_out_i) == nil then global.sprites_fading_out_i = nil end
|
|
|
|
if next(global.sprites_fading_in, nil) == nil and next(global.sprites_fading_out, nil) == nil then
|
|
global.is_fading = false
|
|
global.is_checking = true
|
|
end
|
|
end
|
|
|
|
-- adds chunk to all_chunks
|
|
local function add_chunk(chunk)
|
|
local x = chunk.position.x
|
|
local y = chunk.position.y
|
|
local surface = chunk.surface
|
|
|
|
|
|
-- is needed for RSO
|
|
if global.is_setup == false then
|
|
setup()
|
|
end
|
|
|
|
global.all_chunks[surface.index..":"..x..":"..y] = {position = {x=x,y=y}, surface=surface.index}
|
|
end
|
|
|
|
--deletes chunk from all_chunks and polluted_chunks
|
|
local function remove_chunks(data)
|
|
local positions = data.positions
|
|
local surface_i = data.surface_index
|
|
|
|
for _ , position in pairs(positions) do
|
|
local x = position.x
|
|
local y = position.y
|
|
local r_id = {}
|
|
|
|
if global.polluted_chunks[surface_i..":"..x..":"..y] ~= nil then
|
|
r_id = global.polluted_chunks[surface_i..":"..x..":"..y].r_id
|
|
end
|
|
|
|
for i ,v in pairs(r_id) do
|
|
global.sprites_fading_in[r_id[i]] = nil
|
|
global.sprites_fading_out[r_id[i]] = nil
|
|
rendering.destroy(r_id[i])
|
|
end
|
|
|
|
global.all_chunks[surface_i..":"..x..":"..y] = nil
|
|
global.polluted_chunks[surface_i..":"..x..":"..y] = nil
|
|
end
|
|
end
|
|
|
|
-- wil call if a setting has been changed
|
|
local function setting_changed(data)
|
|
if data.setting == "show-pollution-visuals" then
|
|
local players = get_players_to_render_for()
|
|
for i, chunk_data in pairs(global.polluted_chunks) do
|
|
for x, r_id in pairs(chunk_data.r_id) do
|
|
if #players == 0 then
|
|
rendering.set_visible(r_id, false)
|
|
else
|
|
rendering.set_visible(r_id, true)
|
|
rendering.set_players(r_id, players)
|
|
end
|
|
end
|
|
end
|
|
else
|
|
set_is_setup()
|
|
end
|
|
end
|
|
|
|
-- function that triggers every tick
|
|
local function on_tick()
|
|
if global.is_setup == false then
|
|
--log("setup")
|
|
setup()
|
|
elseif not(global.is_checking) and not(global.is_fading) then
|
|
--log("check polluted chunks")
|
|
check_polluted_chunks()
|
|
elseif global.is_checking then
|
|
--log("check all chunks")
|
|
check_all_chunks()
|
|
elseif global.is_fading then
|
|
--log("fade sprites")
|
|
fade()
|
|
end
|
|
end
|
|
|
|
local function remove_surface(data)
|
|
local remove_data = {}
|
|
remove_data.positions = {}
|
|
remove_data.surface_index = data.surface_index
|
|
for i ,chunk_data in pairs(global.all_chunks) do
|
|
if chunk_data.surface == data.surface_index then
|
|
remove_data.positions[#remove_data.positions+1] = chunk_data.position
|
|
end
|
|
end
|
|
if remove_data.positions ~= {} then
|
|
remove_chunks(remove_data)
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------------------------------
|
|
-- EVENTS
|
|
-------------------------------------------------------------------------
|
|
script.on_event(defines.events.on_chunk_deleted, remove_chunks)
|
|
script.on_event(defines.events.on_chunk_generated, add_chunk)
|
|
script.on_event(defines.events.on_tick, on_tick)
|
|
script.on_event(defines.events.on_runtime_mod_setting_changed, setting_changed)
|
|
script.on_event(defines.events.on_surface_deleted, remove_surface)
|
|
script.on_configuration_changed(set_is_setup)
|
|
script.on_init(set_is_setup) |