diff --git a/Subterranean/control.lua b/Subterranean/control.lua index 5b6776c3..8eb9b72f 100644 --- a/Subterranean/control.lua +++ b/Subterranean/control.lua @@ -1,3 +1,4 @@ +--[[ function Set(list) local set = {} for _, l in ipairs(list) do @@ -275,3 +276,4 @@ function bobsLogisticsOnMine(event) insert_items(game.players[event.player_index], respectiveBelts, calc) end +]]-- --drd \ No newline at end of file diff --git a/Subterranean/data-updates.lua b/Subterranean/data-updates.lua index 77b9912d..0cfd6574 100644 --- a/Subterranean/data-updates.lua +++ b/Subterranean/data-updates.lua @@ -2,13 +2,13 @@ local entity = data.raw["underground-belt"]["green-underground-belt"] if entity ~= nil then --bob's logistics is installed local entity = data.raw["underground-belt"]["green-underground-belt"] entity.max_distance = 250 - table.insert(entity.flags, "not-deconstructable") + --table.insert(entity.flags, "not-deconstructable") end entity = data.raw["underground-belt"]["purple-underground-belt"] if entity ~= nil then --bob's logistics is installed entity.max_distance = 250 - table.insert(entity.flags, "not-deconstructable") + --table.insert(entity.flags, "not-deconstructable") end entity = data.raw["pipe-to-ground"]["nitinol-pipe-to-ground"] diff --git a/Subterranean/locale/en/locale.cfg b/Subterranean/locale/en/locale.cfg index 8f18bc77..5b0de9b2 100644 --- a/Subterranean/locale/en/locale.cfg +++ b/Subterranean/locale/en/locale.cfg @@ -5,24 +5,24 @@ express-subterranean-belt=Express subterranean belt subterranean-pipe=Subterranean pipe [entity-description] -subterranean-pipe=A pipe that can travel underground up to 250 tiles, but charges the player pipes based on distance. -subterranean-belt=A belt that can travel underground up to 250 tiles, but charges the player standard belts based on distance. -fast-subterranean-belt=A faster belt that can travel underground up to 250 tiles, but charges the player fast belts based on distance. -express-subterranean-belt=An express belt that can travel underground up to 250 tiles, but charges the player express belts based on distance. +subterranean-pipe=A pipe that can travel underground up to 250 tiles. +subterranean-belt=A belt that can travel underground up to 250 tiles. +fast-subterranean-belt=A faster belt that can travel underground up to 250 tiles. +express-subterranean-belt=An express belt that can travel underground up to 250 tiles. [item-description] -subterranean-pipe=A pipe that can travel underground up to 250 tiles, but charges the player pipes based on distance. -subterranean-belt=A belt that can travel underground up to 250 tiles, but charges the player standard belts based on distance. -fast-subterranean-belt=A faster belt that can travel underground up to 250 tiles, but charges the player fast belts based on distance. -express-subterranean-belt=An express belt that can travel underground up to 250 tiles, but charges the player express belts based on distance. +subterranean-pipe=A pipe that can travel underground up to 250 tiles. +subterranean-belt=A belt that can travel underground up to 250 tiles. +fast-subterranean-belt=A faster belt that can travel underground up to 250 tiles. +express-subterranean-belt=An express belt that can travel underground up to 250 tiles. [technology-name] subterranean-logistics=Subterranean logistics subterranean-liquid-logistics=Subterranean liquid logistics [technology-description] -subterranean-liquid-logistics=Unlocks the subterranean pipe, which can span 250 tiles and charges the player pipes based on distance. -subterranean-logistics=Unlocks subterranean belts that can span 250 tiles and charges the player the respective type of belts based on distance. +subterranean-liquid-logistics=Unlocks the subterranean pipe, which can span 250 tiles. +subterranean-logistics=Unlocks subterranean belts that can span 250 tiles. [mod-setting-name] diff --git a/Subterranean/prototypes/entity.lua b/Subterranean/prototypes/entity.lua index ce812502..bfd3baf7 100644 --- a/Subterranean/prototypes/entity.lua +++ b/Subterranean/prototypes/entity.lua @@ -4,7 +4,7 @@ local sub_belt_1 = table.deepcopy(data.raw["underground-belt"]["underground-belt sub_belt_1.name = "subterranean-belt" sub_belt_1.minable = {hardness = 0.2, mining_time = 2, result = "subterranean-belt"} sub_belt_1.max_distance = 250 -sub_belt_1.flags = {"placeable-neutral", "player-creation","not-deconstructable"} +--sub_belt_1.flags = {"placeable-neutral", "player-creation","not-deconstructable"} --drd sub_belt_1.max_health = 100 sub_belt_1.structure.direction_in.sheet.tint = {r=1,g=0.3,b=0.1,a=1} sub_belt_1.structure.direction_out.sheet.tint = {r=1,g=0.3,b=0.1,a=1} @@ -18,7 +18,7 @@ local sub_belt_2 = table.deepcopy(data.raw["underground-belt"]["fast-underground sub_belt_2.name = "fast-subterranean-belt" sub_belt_2.minable = {hardness = 0.2, mining_time = 2, result = "fast-subterranean-belt"} sub_belt_2.max_distance = 250 -sub_belt_2.flags = {"placeable-neutral", "player-creation","not-deconstructable"} +--sub_belt_2.flags = {"placeable-neutral", "player-creation","not-deconstructable"} --drd sub_belt_2.max_health = 150 sub_belt_2.structure.direction_in.sheet.tint = {r=1,g=0.1,b=1,a=1} sub_belt_2.structure.direction_out.sheet.tint = {r=1,g=0.1,b=1,a=1} @@ -32,7 +32,7 @@ local sub_belt_3 = table.deepcopy(data.raw["underground-belt"]["express-undergro sub_belt_3.name = "express-subterranean-belt" sub_belt_3.minable = {hardness = 0.2, mining_time = 2, result = "express-subterranean-belt"} sub_belt_3.max_distance = 250 -sub_belt_3.flags = {"placeable-neutral", "player-creation","not-deconstructable"} +--sub_belt_3.flags = {"placeable-neutral", "player-creation","not-deconstructable"} --drd sub_belt_3.max_health = 200 sub_belt_3.structure.direction_in.sheet.tint = {r=0,g=1,b=1,a=1} sub_belt_3.structure.direction_out.sheet.tint = {r=0,g=1,b=1,a=1} @@ -45,7 +45,7 @@ data:extend{sub_belt_3} -- Pipe local subPipe = table.deepcopy(data.raw["pipe-to-ground"]["pipe-to-ground"]) -subPipe.flags = {"placeable-neutral", "player-creation", "not-deconstructable"} +--subPipe.flags = {"placeable-neutral", "player-creation", "not-deconstructable"} --drd subPipe.name = "subterranean-pipe" subPipe.minable = {hardness = 0.2, mining_time = 2, result = "subterranean-pipe"} subPipe.max_distance = 250 diff --git a/Subterranean/settings.lua b/Subterranean/settings.lua index 236306d5..e45ed412 100644 --- a/Subterranean/settings.lua +++ b/Subterranean/settings.lua @@ -1,3 +1,4 @@ +--[[ data:extend({ { type = "int-setting", @@ -49,3 +50,4 @@ data:extend({ }) +]]-- --drd \ No newline at end of file diff --git a/holographic_signs/changelog.txt b/holographic_signs/changelog.txt new file mode 100644 index 00000000..31f38bea --- /dev/null +++ b/holographic_signs/changelog.txt @@ -0,0 +1,126 @@ +--------------------------------------------------------------------------------------------------- +Version: 1.2.3 +Date: 11. 01. 2024 + Changes: + - Turned off holo sign now removes the map tag + - New imputs: Power production/consumption, accumulator charge +--------------------------------------------------------------------------------------------------- +Version: 1.2.2 +Date: 15. 08. 2023 + Changes: + - New imputs: Holographic image (any ingame icon). If playing Warp-Drive-Machine: planet image +--------------------------------------------------------------------------------------------------- +Version: 1.2.1 +Date: 02. 08. 2023 + Bugfix: + - Fixed a reported crash on adding/removing mods (configuration changed) + Changes: + - updates reduced from 5 to 2 seconds + - added remote interface to request hologram refresh + - New inputs for Warp-Drive-Machine mod: time on planet, warp time, natives evolution +--------------------------------------------------------------------------------------------------- +Version: 1.2.0 +Date: 09. 06. 2023 + Changes: + - New input: Production/consumption ratio +--------------------------------------------------------------------------------------------------- +Version: 1.1.1 +Date: 22. 04. 2023 + Changes: + - New input: Pollution +--------------------------------------------------------------------------------------------------- +Version: 1.1.0 +Date: 28. 03. 2023 + Changes: + - New inputs: Fluid consumption, Rocket item launched, Time to finish the research, Played time, Time from last player death + - Some inputs organized in categories (click / expand) +--------------------------------------------------------------------------------------------------- +Version: 1.0.5 +Date: 08. 11. 2022 + Changes: + - Added new input: wind speed (if nullius, windturbines-redux or WindSpeedChanging mods are active) +--------------------------------------------------------------------------------------------------- +Version: 1.0.4 +Date: 31. 10. 2022 + Changes: + - Close the holographic panel GUI in response to E and ESC + - Added blueprint support + - Added new input: day time +--------------------------------------------------------------------------------------------------- +Version: 1.0.3 + Bugfix: + - Fixed a reported crash when a gui is changed and the hologram is invalid +--------------------------------------------------------------------------------------------------- +Version: 1.0.2 + Bugfix: + - Fixed text color change preview + - Fixed gui not responding on god mode scenarios + Changes: + - Added mod option to change text effects: Default, Fast or No animation (thanks to LCStark) +--------------------------------------------------------------------------------------------------- +Version: 1.0.1 + Bugfix: + - Fixed a crash when a mod is removed and the hologram was using some of its icons/names + Changes: + - Added mod option to enable/disbale hologram animation +--------------------------------------------------------------------------------------------------- +Version: 1.0.0 + Changes: + - New graphics + - Added switch to turn on / off the hologram + - You can turn OFF the hologram with circuit signal-red=1 and ON with signal-green=1 + - You can use these commands to turn ON/OFF all holograms (admin only): /hologram-turn-on /hologram-turn-off +--------------------------------------------------------------------------------------------------- +Version: 0.1.0 + Bugfix: + - Fixed lab progress print to integer values from 1 - 100% +--------------------------------------------------------------------------------------------------- +Version: 0.0.9 + Bugfix: + - Fixed a reported crash regarding '%' text replacement +--------------------------------------------------------------------------------------------------- +Version: 0.0.8 + Bugfix: + - Fixed a problem with fluid production/consumption, that could cause a crash + - Fixed text format on some input values + Changes: + - Added option to print plain text instead of hologram +--------------------------------------------------------------------------------------------------- +Version: 0.0.7 + Bugfix: + - Fixed a reported crash + Changes: + - New button icons + - Added RGB text color editor +--------------------------------------------------------------------------------------------------- +Version: 0.0.6 + Changes: + - Copy-paste implemented + - You can now print input values in the middle of your custom text, using the tag |#| + - Added new inputs: kill count, player casualties, enemy evolution +--------------------------------------------------------------------------------------------------- +Version: 0.0.5 + Bugfix: + - Fixed a reported crash regarding empty world tag + Changes: + - Empty text/icon will clear the hologram bubble +--------------------------------------------------------------------------------------------------- +Version: 0.0.4 + Changes: + - Added new inputs for production/consumption statistics +--------------------------------------------------------------------------------------------------- +Version: 0.0.3 + Changes: + - Added the ability to read and print circuit values, logistic item count and other force stats +--------------------------------------------------------------------------------------------------- +Version: 0.0.2 + Bugfix: + - Fixed a crash with a possible invalid signal icon + Changes: + - Added textbox option + - Made compatible with space exploration to allow building on space platform +--------------------------------------------------------------------------------------------------- +Version: 0.0.1 +Date: 18.10.2021 + Info: + - Initial release \ No newline at end of file diff --git a/holographic_signs/control.lua b/holographic_signs/control.lua new file mode 100644 index 00000000..a162140e --- /dev/null +++ b/holographic_signs/control.lua @@ -0,0 +1,1076 @@ +require "util" +require "utils" +require "speech-bubbles" +local format_number = util.format_number + +function d_format_number(number, form) +if not form then form = "%.2f" end +return string.format(form, number) +end + + + +local inputs = + { + "hs_hologram_image", + "hs_signal", + "hs_logistic", + "hs_production_m", + "hs_consumption_m", + "hs_research", + "hs_rockets", + "hs_players", + "hs_enemy_evolution", + "hs_kill_count", +-- "hs_wind_speed", + "hs_timers", + "hs_pollution", + "hs_charge" + } + +local sub_inputs = { + ['hs_research'] = {'hs_research_progress','hs_research_time_remaining'}, + ['hs_timers'] = {'hs_total_time','hs_day_time','hs_time_from_last_death'}, + ['hs_rockets'] = {"hs_rockets_launched","hs_item_launched"}, + ['hs_production_m'] = {"hs_production","hs_production_f","hs_production_p","hs_production_ratio","hs_production_ratio_f"}, + ['hs_consumption_m'] = {"hs_consumption","hs_consumption_f","hs_consumption_p"}, + ['hs_players'] = {"hs_player_casualties","hs_connected_players"}, + ['hs_warpdrive'] = {"hs_wdm_warping_in","hs_wdm_time_on_planet", "hs_native_evolution", "hs_planet_image"}, + } + +local cb_opts = {'[img=utility/time_editor_icon]05 s','[img=utility/time_editor_icon]01 m','[img=utility/time_editor_icon]10 m','[img=utility/time_editor_icon]01 h','[img=utility/time_editor_icon]15 h','[img=infinity]'} + +local sub_options = { + ['hs_production_ratio'] = {type = "drop-down", options=cb_opts }, + ['hs_production_ratio_f'] = {type = "drop-down", options=cb_opts}, + } + + + +local pk_item_list = {"hs_logistic","hs_production","hs_consumption","hs_item_launched","hs_production_ratio"} +local pk_fluid_list = {"hs_production_f","hs_consumption_f","hs_production_ratio_f"} +local pk_entity_list = {"hs_kill_count"} +local pk_signal_list = {"hs_hologram_image","hs_signal"} + + + +function setup_mod_vars() +global.entity_speech = global.entity_speech or {} +global.signs = global.signs or {} +global.players = global.players or {} -- to control opened guis +global.last_death_tick = global.last_death_tick or 0 +global.force_research = global.force_research or {} + +global.inputs = table.deepcopy(inputs) +global.sub_inputs = table.deepcopy(sub_inputs) +--[[global.signs[1] = {entity = + text= + icon = + add_tag= + maptag=}]] +if game.active_mods['shield-projector'] then + global.animation = 'hs_hologram_animated' + else + global.animation = 'hs_hologram' + end +if game.active_mods['WindSpeedChanging'] or game.active_mods['nullius'] or game.active_mods['windturbines-redux'] then add_list(global.inputs, "hs_wind_speed") end +if game.active_mods['Warp-Drive-Machine'] then add_list(global.inputs, "hs_warpdrive") add_list(global.inputs, "hs_wind_speed") end + +ReadRunTimeSettings() +end + + + + +function on_init() +setup_mod_vars() +if game and game.forces.player.technologies['optics'] and game.forces.player.technologies['optics'].researched and (not game.forces.player.recipes['hs_holo_sign'].enabled) then + game.forces.player.recipes['hs_holo_sign'].enabled=true + end +end + +function on_configuration_changed() +setup_mod_vars() +ValidateAllSigns() +end +script.on_init(on_init) +script.on_configuration_changed(on_configuration_changed) + + +function ReadRunTimeSettings(event) +global.opt_animation = settings.global["hs-opt-animation"].value +ValidateAnimations() +end +script.on_event(defines.events.on_runtime_mod_setting_changed, ReadRunTimeSettings) + + + +function ValidateAnimations() +for UN, Sign_Data in pairs (global.signs) do + local animation = Sign_Data.animation + local entity = Sign_Data.entity + if animation and rendering.is_valid(animation) and (not global.opt_animation) then rendering.destroy(animation) Sign_Data.animation=nil end + if global.opt_animation and ((not animation) or (not rendering.is_valid(animation))) then + if global.animation == 'hs_hologram_animated' then + animation = rendering.draw_animation { + animation = 'hs_hologram_animated', + x_scale=0.07,y_scale=0.35, + target = entity, + target_offset = {0, -1.1}, + surface = entity.surface, + animation_offset = 0} + else + animation = rendering.draw_sprite { + sprite = 'hs_hologram', + x_scale=0.4,y_scale=0.5, + target = entity, + target_offset = {0, -1.1}, + surface = entity.surface} + end + Sign_Data.animation = animation + end + end +end + + + +function is_valid_input(input) +local valid = false +if in_list(global.inputs, input) then valid=true +else +for g,tab in pairs (global.sub_inputs) do + if in_list(tab, input) then valid=true break end + end +end +return valid +end + + +-- avoid crash if removed mod icons +function ValidateAllSigns() +for UN, Sign_Data in pairs (global.signs) do + local entity = Sign_Data.entity + local icon = Sign_Data.icon + local input = Sign_Data.input + -- Manage INPUTS + if input then + if in_list(pk_signal_list, input) then --'hs_signal' + local signal = Sign_Data.input_signal + if signal then + if signal.type=='item' then if not game.item_prototypes[signal.name] then Sign_Data.input=nil end + elseif signal.type=='fluid' then if not game.fluid_prototypes[signal.name] then Sign_Data.input=nil end + elseif signal.type=='virtual' then if not game.virtual_signal_prototypes[signal.name] then Sign_Data.input=nil end + end + end + elseif in_list(pk_item_list, input) then + local item = Sign_Data.input_item + if not (item and game.item_prototypes[item]) then Sign_Data.input=nil end + elseif in_list(pk_fluid_list, input) then + local fluid = Sign_Data.input_fluid + if not (fluid and game.fluid_prototypes[fluid]) then Sign_Data.input=nil end + elseif input=='hs_kill_count' then + local killed = Sign_Data.input_entity + if not (killed and game.entity_prototypes[killed]) then Sign_Data.input=nil end + + elseif not is_valid_input(input) then Sign_Data.input=nil end + end + -- MAP TAG + if icon and icon.type and icon.name then + if icon.type=='item' then if not game.item_prototypes[icon.name] then Sign_Data.icon=nil end + elseif icon.type=='fluid' then if not game.fluid_prototypes[icon.name] then Sign_Data.icon=nil end + elseif icon.type=='virtual' then if not game.virtual_signal_prototypes[icon.name] then Sign_Data.icon=nil end + end + end + end +end + + + + + + + +---Gui creation + +function add_gui(parent,element,destroy,style) +local E = parent[element.name] +if destroy and E then E.destroy() E=nil end +if not E then E=parent.add(element) end +if style then for s=1,#style do E.style[style[s][1]]=style[s][2] end end +return E +end + + + +local function open_gui (player, entity) +if not (entity and entity.valid) then return end + +local gui = player.gui.screen +--player.opened = nil + +local UN = entity.unit_number +local Sign_Data = global.signs[UN] or {} + +if not Sign_Data.entity then Sign_Data.entity=entity end + +global.players[player.name] = Sign_Data + +--gui.clear() + +if gui.frame_holo_sign then gui.frame_holo_sign.destroy() end + +local frame = add_gui(player.gui.screen,{type = "frame", name = "frame_holo_sign", caption ={'','[img=item/hs_holo_sign]',{'holographic_sign'}}, direction = "vertical"}) +player.opened = frame +frame.style.minimal_width = 100 +frame.auto_center = true +local tab = add_gui(frame, {type="table", name='tab1', column_count = 3}) + +tab.add{type = "label", caption = {'hs_icon'}}.style.font = "default-bold" +tab.add{type = "label", caption = {'hs_text'}}.style.font = "default-bold" +tab.add{type="switch",name='hs_sw_onoff', tooltip={'hs_on_off'}, allow_none_state = false, switch_state=Sign_Data.state or 'right'} + + +local ico = add_gui(tab, {type="choose-elem-button", name='hs_icon_bt', elem_type="signal"} ) --elem_type ='item' item='steel-plate' elem_value +ico.elem_value= Sign_Data.icon +local txt = add_gui(tab, {type="textfield", name='hs_text_field' , text =Sign_Data.text} ) +local ico = add_gui(tab, {type="choose-elem-button", name='hs_icon_bt', elem_type="signal"} ) --elem_type ='item' item='steel-plate' elem_value + +local btc = add_gui(tab, {type="sprite-button", name='bt_hs_text_color', tooltip={'hs_color'}, style = "tool_button", sprite = "utility/brush_icon"}) + + +local tab = add_gui(frame, {type="table", name='tab_cb', column_count = 2}) +tab.add{type="checkbox",name='hs_cb_add_map', caption={'hs_add_tag'}, state=Sign_Data.add_tag or false}.style.font = "default-bold" +tab.add{type="checkbox",name='hs_cb_plain_text', caption={'hs_plain_text'}, state=Sign_Data.plain_text or false}.style.font = "default-bold" + +local tab = add_gui(frame, {type="table", name='tab3', column_count = 4}) +add_gui(tab, {type="sprite-button", sprite = "utility/close_white", name='bt_destroy_my_2parent', style = "back_button" }) --style='rounded_button'style="tool_button" +add_gui(tab, {type="sprite-button", name='bt_holo_sign_textbox', tooltip={'bt_holo_sign_textbox'}, style = "tool_button", sprite = "utility/custom_tag_icon"}) --rename_icon_normal +add_gui(tab, {type="sprite-button", name='bt_holo_sign_inputs', tooltip={'bt_holo_sign_inputs'},style = "tool_button", sprite = "utility/logistic_network_panel_black" }) --"item/red-wire" +add_gui(tab, {type="button", caption ='OK', name='bt_holo_sign_ok', tooltip={'bt_holo_sign_confirm'}, style = "confirm_button"}) + + + +if Sign_Data.input then add_inputs(frame,player) end +if Sign_Data.show_textbox then add_textbox(frame,player) end + + +--frame.force_auto_center() +end + + + + + +-- RGB Color editor +function show_team_color_gui(gui,player) + +local Sign_Data = global.players[player.name] +local color = Sign_Data.text_color or {r = 1, g = 1, b = 1} +local frame = gui.hs_color_frame + if frame then frame.destroy() + else + frame = gui.add{type="frame", name="hs_color_frame", direction = "vertical", caption={"hs_color"}} --style=mod_gui.frame_style, + + local tabBars = frame.add{type = "table", name='hs_tab_rgb', column_count = 2} + tabBars.add{type = "label", caption='R'}.style.font_color={r = 1, g = 0.5, b = 0.5} + local sliderR = tabBars.add{type = "slider", name='hs_slider_color_R', value = color.r,minimum_value=0,maximum_value=1} + + tabBars.add{type = "label", caption='G'}.style.font_color={r = 0.5, g = 1, b = 0.5} + local sliderG = tabBars.add{type = "slider", name='hs_slider_color_G', value = color.g,minimum_value=0,maximum_value=1} + + tabBars.add{type = "label", caption='B'}.style.font_color={r = 0.5, g = 0.5, b = 1} + local sliderB = tabBars.add{type = "slider", name='hs_slider_color_B', value = color.b,minimum_value=0,maximum_value=1} + + local tabBarsBt = frame.add{type = "table", name='hs_color_bt_tab', column_count = 3} + + local btCancel= tabBarsBt.add{name="bt_destroy_my_2parent", type="sprite-button", style = "slot_button", sprite = "utility/deconstruction_mark"} --rounded_button --back_button + local btApply = tabBarsBt.add{name="bt_hs_color_apply", type="sprite-button", style = "slot_button", sprite = "utility/check_mark_green"} --confirm_slot + local label = tabBarsBt.add{name="label_hs_color", type="label", caption={"hs_color"}} --confirm_slot + label.style.font_color = color + label.style.font = "default-large-bold" + end +end + + +function color_apply(gui,player) +local Sign_Data = global.players[player.name] + +if gui and gui.hs_tab_rgb then + local R = gui.hs_tab_rgb.hs_slider_color_R.slider_value + local G = gui.hs_tab_rgb.hs_slider_color_G.slider_value + local B = gui.hs_tab_rgb.hs_slider_color_B.slider_value + Sign_Data.text_color = {r = R, g = G, b = B} + gui.destroy() + end +end + + +local function on_gui_value_changed(event) +local gui = event.element +local player = game.players[event.player_index] + +if gui.get_mod()=='holographic_signs' then +if gui.type=='slider' then + if gui.name=='hs_slider_color_R' or gui.name=='hs_slider_color_G' or gui.name=='hs_slider_color_B' then + local tab = gui.parent + local R=tab.hs_slider_color_R.slider_value + local G=tab.hs_slider_color_G.slider_value + local B=tab.hs_slider_color_B.slider_value + local tab = tab.parent + tab.hs_color_bt_tab.label_hs_color.style.font_color = {r=R,g=G,b=B} + end + end +end + +end +script.on_event(defines.events.on_gui_value_changed, on_gui_value_changed) + + + + + + +local function on_gui_switch_state_changed(event) +local gui = event.element +local player = game.players[event.player_index] +if gui.get_mod()=='holographic_signs' then + if gui.name=="hs_sw_onoff" then + local Sign_Data = global.players[player.name] + Sign_Data.state = gui.switch_state + apply_holo_sign(Sign_Data) + end + end +end +script.on_event(defines.events.on_gui_switch_state_changed, on_gui_switch_state_changed) + + + +local function on_gui_click(event) +local gui = event.element +local player = game.players[event.player_index] + +if not (player) then return end +if not (gui and gui.valid) then return end + +if gui.name and gui.name~='' then + if gui.name == "bt_holo_sign_ok" then add_holo_sign(gui.parent.parent,player,event.shift) + elseif gui.name == "bt_destroy_my_parent" then gui.parent.destroy() + elseif gui.name == "bt_destroy_my_2parent" then gui.parent.parent.destroy() + elseif gui.name == "bt_holo_sign_textbox" then toggle_textbox(gui.parent.parent,player) + elseif gui.name == "bt_holo_sign_inputs" then toggle_inputs(gui.parent.parent,player) + elseif gui.name == "bt_hs_cancel_input" then cancel_input(gui.parent.parent.parent,player) return + elseif gui.name == "bt_hs_text_color" then show_team_color_gui(gui.parent.parent,player) return + elseif gui.name == "bt_hs_color_apply" then color_apply(gui.parent.parent,player) return + end +end +end +script.on_event(defines.events.on_gui_click, on_gui_click) + +function toggle_textbox(gui,player) +if gui.hs_textbox then + gui.hs_textbox.destroy() + else + add_textbox(gui,player) + end +end + +function toggle_inputs(gui,player) +if gui.hs_inputs then + gui.hs_inputs.destroy() + else + add_inputs(gui,player) + end +end + +function cancel_input(gui,player) +local Sign_Data = global.players[player.name] +if Sign_Data then Sign_Data.input = nil end +toggle_inputs(gui,player) +end + + +function add_inputs(gui,player) +local Sign_Data = global.players[player.name] + if gui.hs_inputs then gui.hs_inputs.destroy() end + local input = Sign_Data.input + local frame = gui.add{type="frame", name="hs_inputs",caption={"hs_input_box"}, direction='vertical'} + frame.style.width=290 + --frame.style.height=100 + -- will need scroll-pane here + + + --game.print(input) + if not input then + for i=1, #global.inputs do + frame.add{type="radiobutton",name=global.inputs[i], caption={global.inputs[i]}, state=iif(global.inputs[i]==input, true, false) }.style.font = "default-bold" + end + else + + + local tab = add_gui(frame, {type="table", name='tab_inp_sel', column_count = 2}) + tab.add{type="label",name=input, caption={input}}.style.font = "default-bold" + tab.add{name="bt_hs_cancel_input", type="sprite-button", sprite = "utility/close_black", style = "shortcut_bar_button_small"} + + if global.sub_inputs[input] then + for i=1, #global.sub_inputs[input] do + frame.add{type="radiobutton",name=global.sub_inputs[input][i], caption={global.sub_inputs[input][i]}, state=iif(global.sub_inputs[input][i]==input, true, false) }.style.font = "default-bold" + end + end + + if in_list(pk_signal_list, input) then + local ico = add_gui(frame, {type="choose-elem-button", name='hs_choose_input', elem_type="signal"} ) --elem_type ='item' item='steel-plate' elem_value + ico.elem_value= Sign_Data.input_signal + + elseif (in_list(pk_item_list, input)) then + local ico = add_gui(frame, {type="choose-elem-button", name='hs_choose_item', elem_type="item"} ) --elem_type ='item' item='steel-plate' elem_value + ico.elem_value= Sign_Data.input_item + + elseif (in_list(pk_entity_list, input)) then + local ico = add_gui(frame, {type="choose-elem-button", name='hs_choose_entity', elem_type="entity", elem_filters={{type = "entity", filter = "entity-with-health"}} } ) --elem_type ='item' item='steel-plate' elem_value + ico.elem_value= Sign_Data.input_entity + + elseif (in_list(pk_fluid_list,input)) then + local ico = add_gui(frame, {type="choose-elem-button", name='hs_choose_fluid', elem_type="fluid"} ) --elem_type ='item' item='steel-plate' elem_value + ico.elem_value= Sign_Data.input_fluid + -- else + -- tab.add{type="label"} + end + + if sub_options[input] then + local t=sub_options[input].type + if t=="drop-down" then add_gui(frame, {type=t, name=t,items=sub_options[input].options, selected_index = Sign_Data.sub_option or 1}) end + end + + --add_gui(frame, {type="sprite-button", sprite = "utility/close_white", name='bt_back_input', style = "back_button"}) + + end +-- frame.style.horizontally_stretchable=false +end + + +local function on_gui_checked_state_changed(event) +local gui = event.element +if gui.get_mod()=='holographic_signs' then + local player = game.players[event.player_index] + --if in_list(global.inputs,gui.name) or in_list(global.sub_inputs[1],gui.name) or in_list(global.sub_inputs[2],gui.name) then + if gui.parent.name=='hs_inputs' then + local Sign_Data = global.players[player.name] + Sign_Data.input = gui.name + add_inputs(gui.parent.parent,player) + end +end +end +script.on_event(defines.events.on_gui_checked_state_changed, on_gui_checked_state_changed) + + + +function add_textbox(gui,player) +local Sign_Data = global.players[player.name] + local textbox = gui.add{type="text-box", name="hs_textbox",text=Sign_Data.textbox} + textbox.style.width=290 + textbox.style.height=100 --300 + textbox.style.horizontally_stretchable=false + textbox.word_wrap=true +end + + + +function add_holo_sign(gui,player,k_shift) +local Sign_Data = global.players[player.name] +local entity = Sign_Data.entity + +if entity and entity.valid then + local text = gui.tab1.hs_text_field.text + local icon = gui.tab1.hs_icon_bt.elem_value + local add_tag = gui.tab_cb.hs_cb_add_map.state + local plain_text = gui.tab_cb.hs_cb_plain_text.state + local big_hologram_render = Sign_Data.big_hologram_render + if big_hologram_render then + if big_hologram_render and rendering.is_valid(big_hologram_render) then rendering.destroy(big_hologram_render) end + Sign_Data.big_hologram_render = nil + end + if gui.hs_textbox then + Sign_Data.show_textbox = true + Sign_Data.textbox = gui.hs_textbox.text + else + Sign_Data.show_textbox = false + end + if gui.hs_inputs then + if in_list(pk_signal_list, Sign_Data.input) then + Sign_Data.input_signal = gui.hs_inputs.hs_choose_input.elem_value + --if k_shift then icon = Sign_Data.input_signal game.print (icon) end + elseif in_list(pk_item_list, Sign_Data.input) then + Sign_Data.input_item = gui.hs_inputs.hs_choose_item.elem_value + --if k_shift then icon = Sign_Data.input_item game.print (icon) end + elseif in_list(pk_fluid_list, Sign_Data.input) then + Sign_Data.input_fluid = gui.hs_inputs.hs_choose_fluid.elem_value + --if k_shift then icon = Sign_Data.input_fluid game.print (icon)end + elseif in_list(pk_entity_list, Sign_Data.input) then + Sign_Data.input_entity = gui.hs_inputs.hs_choose_entity.elem_value + --if k_shift then icon = Sign_Data.input_entity game.print (icon)end + else + --Sign_Data.input = nil + end + + if sub_options[Sign_Data.input] then + local t = sub_options[Sign_Data.input].type + local sub_option + if t=='drop-down' then sub_option = gui.hs_inputs[t].selected_index end + Sign_Data.sub_option=sub_option + end + + + else + Sign_Data.input = nil + end + + Sign_Data.text = text + Sign_Data.icon = icon + Sign_Data.add_tag = add_tag + Sign_Data.plain_text= plain_text + + Sign_Data.last_user = player.name + + apply_holo_sign(Sign_Data) + end +gui.destroy() +end + + + + +local function on_gui_opened(event) + local player_index = event.player_index + local player = game.players[player_index] + if event.entity and event.entity.valid and event.entity.name=='hs_holo_sign' then + open_gui(player, event.entity) + else + local gui = player.gui.screen + if gui.frame_holo_sign then + if player.opened ~= gui.frame_holo_sign then gui.frame_holo_sign.destroy() end + end + end +end +script.on_event(defines.events.on_gui_opened, on_gui_opened) + + +local function on_gui_closed(event) + if event.element and event.element.valid and event.element.name == 'frame_holo_sign' then + event.element.destroy() + end +end +script.on_event(defines.events.on_gui_closed, on_gui_closed) + + + +function apply_holo_sign(Sign_Data) + local function get_precision_index(opt) + local def = { + defines.flow_precision_index.five_seconds, + defines.flow_precision_index.one_minute, + defines.flow_precision_index.ten_minutes, + defines.flow_precision_index.one_hour, + defines.flow_precision_index.fifty_hours, + defines.flow_precision_index.one_thousand_hours + } + return def[opt] or defines.flow_precision_index.one_minute + end + +local entity = Sign_Data.entity + +if entity and entity.valid then +local force = entity.force +local text = Sign_Data.text or '' +local icon = Sign_Data.icon +local add_tag = Sign_Data.add_tag +local input = Sign_Data.input +local color = Sign_Data.text_color or {r=255,g=255,b=255} +local plain_text = Sign_Data.plain_text +local the_plain_text = Sign_Data.the_plain_text +local animation = Sign_Data.animation +local big_hologram_render = Sign_Data.big_hologram_render + +local state = Sign_Data.state or 'right' -- left=off right=on + +local is_it_on = true + +if global.all_turned_off==true or state=='left' then is_it_on = false end + +-- Manage INPUTS +local ipt, holo_img,img_scale +if is_it_on then + if input then + if input=='hs_signal' then + local signal = Sign_Data.input_signal + if signal and signal.type and signal.name then + ipt = format_number (entity.get_merged_signal(signal)) --get signal + end + elseif input=='hs_hologram_image' then + local signal = Sign_Data.input_signal + if signal and signal.type and signal.name then + img_scale = 2 + if signal.type=='virtual' then + holo_img ='virtual-signal/'..signal.name + + else + holo_img =signal.type .. '/'..signal.name + end + end + elseif input=='hs_logistic' then + local item = Sign_Data.input_item + local logistic_network = entity.surface.find_logistic_network_by_position(entity.position, force) + if item and logistic_network then + ipt = logistic_network.get_item_count(item) --get signal + end + + elseif in_list({'hs_production','hs_consumption','hs_item_launched'},input) then + local item = Sign_Data.input_item + if item then + local count + if input=='hs_production' then count = force.item_production_statistics.get_input_count(item) + elseif input=='hs_consumption' then count = force.item_production_statistics.get_output_count(item) + elseif input=='hs_item_launched' then count = force.get_item_launched(item) + end + ipt = format_number(count) + end + + elseif input=='hs_production_ratio' then + local item = Sign_Data.input_item + if item then + local sub_option = Sign_Data.sub_option + sub_option = get_precision_index(sub_option) + local count = force.item_production_statistics.get_flow_count{name=item,input=true, precision_index=sub_option} + local cons = force.item_production_statistics.get_flow_count{name=item,input=false, precision_index=sub_option} + local ratio = 0 + if cons>0 then ratio=count/cons end + ipt = math.ceil(count) .. '/' .. math.ceil(cons) .. iif(count>=cons,'[img=virtual-signal/signal-green]','[img=virtual-signal/signal-red]').. d_format_number(ratio, "%.1f") + end + + elseif input=='hs_production_ratio_f' then + local fluid = Sign_Data.input_fluid + if fluid then + local sub_option = Sign_Data.sub_option + sub_option = get_precision_index(sub_option) + local count = force.fluid_production_statistics.get_flow_count{name=fluid,input=true, precision_index=sub_option} + local cons = force.fluid_production_statistics.get_flow_count{name=fluid,input=false, precision_index=sub_option} + local ratio = 0 + if cons>0 then ratio=count/cons end + ipt = my_format_number(math.ceil(count) , 1000000).. '/' .. my_format_number(math.ceil(cons), 1000000) .. iif(count>=cons,'[img=virtual-signal/signal-green]','[img=virtual-signal/signal-red]').. d_format_number(ratio, "%.1f") + end + + + elseif input=='hs_production_f' or input=='hs_consumption_f' then + local fluid = Sign_Data.input_fluid + if fluid then + local count + if input=='hs_production_f' then count = force.fluid_production_statistics.get_input_count(fluid) + elseif input=='hs_consumption_f' then count = force.fluid_production_statistics.get_output_count(fluid) + end + ipt = my_format_number(math.floor(count), 1000000) + end + + elseif input=='hs_production_p' or input=='hs_consumption_p' then + local pole = entity.surface.find_entities_filtered{type='electric-pole', force=force, position=entity.position, radius=2, limit=1} + if pole[1] then + local NS = pole[1].electric_network_statistics + local cons=0 + local prod=0 + -- prod + for n,v in pairs (NS.output_counts) do + prod = prod + NS.get_flow_count{name=n,input=false, precision_index=defines.flow_precision_index.five_seconds, sample=1} + end + -- cons + for n,v in pairs (NS.input_counts) do + cons = cons + NS.get_flow_count{name=n,input=true, precision_index=defines.flow_precision_index.five_seconds, sample=1} + end + + prod=prod*60/1000000 + cons=cons*60/1000000 + + if input=='hs_production_p' then ipt =d_format_number(prod, "%.1f").. " MJ" + elseif input=='hs_consumption_p' then ipt = d_format_number(cons, "%.1f") .. " MJ" + end + end + + + elseif input=='hs_charge' then + local ch,t =0,0 + local acc = entity.surface.find_entities_filtered{type='accumulator', force=force} + for _,a in pairs(acc) do + ch = ch + a.energy + t = t + a.electric_buffer_size + end + ipt = d_format_number(ch/1000000, "%.1f") .. " / " .. d_format_number(t/1000000, "%.1f") .. " MJ" + + + elseif input=='hs_research_progress' then + if force.research_progress then ipt = d_format_number(force.research_progress*100, "%.1f") end --.. '%' + elseif input=='hs_rockets_launched' then + ipt = format_number(force.rockets_launched ) + elseif input=='hs_connected_players' then + ipt = #force.connected_players + elseif input=='hs_player_casualties' then + ipt = force.kill_count_statistics.get_output_count('character') + elseif input=='hs_enemy_evolution' then + ipt = format_evolution(game.forces.enemy) -- .. '%' + elseif input=='hs_kill_count' then + local killed = Sign_Data.input_entity + if killed then ipt = format_number(force.kill_count_statistics.get_input_count(killed)) end + elseif input=='hs_wind_speed' then + ipt = d_format_number(entity.surface.wind_speed*100, "%.1f") -- 'default 0.02' + elseif input=='hs_day_time' then + ipt = getDayTimeString(entity.surface) + + elseif input=='hs_total_time' then + ipt = format_time_hour(game.tick) + elseif input=='hs_time_from_last_death' then + ipt = format_time_from_tick(global.last_death_tick) + + elseif input=='hs_research_time_remaining' then + ipt = get_force_research_time_remaining(force) + + elseif input=='hs_pollution' then + ipt = d_format_number(entity.surface.get_pollution(entity.position)) + + --WARP DRIVE MACHINE remote interface + elseif input=='hs_wdm_warping_in' then + ipt = remote.call("WDM","get_ship_warp_time",force.name) + elseif input=='hs_wdm_time_on_planet' then + ipt = remote.call("WDM","get_ship_planet_time",force.name) + elseif input=='hs_native_evolution' then + ipt = remote.call("WDM","get_planet_natives_evolution",force.name) + elseif input=='hs_planet_image' then + holo_img = remote.call("WDM","get_planet_image",force.name) + img_scale = 0.65 + end + end + + + local iss, ise + if ipt then + iss, ise = string.find(text, '|#|') + if iss then + text = string.gsub(text, '|#|', ipt) + else + text = text.. ' ' .. ipt + end + end + + end + + +local pt = text +if icon and icon.type and icon.name and (not plain_text) then + pt = '[img=' .. iif(icon.type=='virtual','virtual-signal', icon.type) .. '/' .. icon.name ..']' .. text + end + +local destroy_plan_text = false +clear_speach_bubble(entity) + +if (pt~='' or holo_img) and is_it_on then + if pt~='' then + if plain_text then + if the_plain_text and rendering.is_valid(the_plain_text) then + rendering.set_color(the_plain_text, color) + rendering.set_text(the_plain_text, pt) + else + the_plain_text = rendering.draw_text{text=pt, surface=entity.surface, target=entity, color=color,target_offset={-1,-1} } + Sign_Data.the_plain_text = the_plain_text + end + else + if the_plain_text then destroy_plan_text =true end + pt = '[color=' .. color.r ..',' .. color.g ..',' .. color.b ..']' .. pt .. '[/color]' + Entity_Speak(entity,pt) + end + end + + + if holo_img then + if big_hologram_render and rendering.is_valid(big_hologram_render) then + if rendering.get_sprite(big_hologram_render) ~= holo_img then rendering.set_sprite(big_hologram_render, holo_img) end + else + big_hologram_render = rendering.draw_sprite { + sprite = holo_img, + x_scale=img_scale,y_scale=img_scale, + target = entity, + target_offset = {0, -2}, + surface = entity.surface} + Sign_Data.big_hologram_render=big_hologram_render + end + end + + + if global.opt_animation and ((not animation) or (not rendering.is_valid(animation))) then + if global.animation == 'hs_hologram_animated' then + animation = rendering.draw_animation { + animation = 'hs_hologram_animated', + x_scale=0.07,y_scale=0.35, + target = entity, + target_offset = {0, -1.1}, + surface = entity.surface, + animation_offset = 0} + else + animation = rendering.draw_sprite { + sprite = 'hs_hologram', + x_scale=0.4,y_scale=0.5, + target = entity, + target_offset = {0, -1.1}, + surface = entity.surface} + end + Sign_Data.animation = animation + end + + else + if the_plain_text then destroy_plan_text =true end + if animation and rendering.is_valid(animation) then rendering.destroy(animation) Sign_Data.animation=nil end + if big_hologram_render and rendering.is_valid(big_hologram_render) then rendering.destroy(big_hologram_render) Sign_Data.big_hologram_render=nil end + end + +if destroy_plan_text then + rendering.destroy(the_plain_text) + Sign_Data.the_plain_text = nil + end + + +-- MAP TAG +if Sign_Data.maptag and Sign_Data.maptag.valid then Sign_Data.maptag.destroy() end +if add_tag and is_it_on then + local ico + if icon and icon.type and icon.name then ico=icon end + if ico or (text~='') then + local tag = {icon=ico,text=text,position=entity.position} + local thetag = force.add_chart_tag(entity.surface,tag) + Sign_Data.maptag = thetag + end + end + +local UN = entity.unit_number +global.signs[UN]=Sign_Data +end +end + + + + +function update_force_research_durations(force, current_research) + local force_table = global.force_research[force.name] + local current_progress = force.research_progress + local research_time = current_research.research_unit_energy * get_research_unit_count(current_research) + + local last_research_progress = force_table.last_research_progress or 0 + local last_research_progress_tick = force_table.last_research_progress_tick or 0 + local progress_delta = current_progress - last_research_progress + local tick_delta = game.tick - last_research_progress_tick + + local research_speed = (progress_delta * research_time) / tick_delta + + force_table.last_research_progress = current_progress + force_table.last_research_progress_tick = game.tick + force_table.research_speed = research_speed + + local duration_text = "[img=infinity]" + if research_speed > 0 then + local level = current_research.level + local progress = get_research_progress(current_research, level) + local duration = (1 - progress) + * get_research_unit_count(current_research, level) + * current_research.research_unit_energy + / research_speed + duration_text = format_t(duration) + end + force_table.duration_text = duration_text +end + + + +function get_force_research_time_remaining(force) +if not global.force_research[force.name] then global.force_research[force.name] = {} end + +local last_check = global.force_research[force.name].last_research_progress_tick or 0 +if game.tick - last_check > 60 then + local current_research = force.current_research + if current_research then + update_force_research_durations(force, current_research) + else + global.force_research[force.name].duration_text = "[img=infinity]" + end + end +return global.force_research[force.name].duration_text +end + + +function Copy_Sign_Data(Entity, Sign_Data) + Sign_Data.entity = Entity + Sign_Data.maptag = nil + Sign_Data.animation = nil + Sign_Data.the_plain_text = nil + Sign_Data.big_hologram_render=nil + local NUN = Entity.unit_number + if global.signs[NUN] then + if global.signs[NUN].the_plain_text then + rendering.destroy(global.signs[NUN].the_plain_text) + global.signs[NUN].the_plain_text=nil + end + if global.signs[NUN].animation then + rendering.destroy(global.signs[NUN].animation) + global.signs[NUN].animation=nil + end + if global.signs[NUN].big_hologram_render then + rendering.destroy(global.signs[NUN].big_hologram_render) + global.signs[NUN].big_hologram_render=nil + end + + + if global.signs[NUN].maptag and global.signs[NUN].maptag.valid then global.signs[NUN].maptag.destroy() end + end + global.signs[NUN] = Sign_Data + apply_holo_sign(Sign_Data) +end + + +function on_entity_cloned(event) +local new = event.destination +local old = event.source +if new.name=='hs_holo_sign' and old.name=='hs_holo_sign' then +local UN = old.unit_number +if global.signs[UN] then + local Sign_Data = table.deepcopy(global.signs[UN]) + Copy_Sign_Data(new, Sign_Data) + end + end +end +script.on_event(defines.events.on_entity_cloned, on_entity_cloned, {{filter = "name", name = 'hs_holo_sign'}}) +script.on_event(defines.events.on_entity_settings_pasted, on_entity_cloned) + + + +function on_player_setup_blueprint(event) + local player = game.get_player(event.player_index) + if not (player and player.valid) then return end + + local item = player.cursor_stack + if not (item and item.valid_for_read) then + item = player.blueprint_to_setup + if not (item and item.valid_for_read) then return end + end + local count = item.get_blueprint_entity_count() + if count == 0 then return end + + for index, entity in pairs(event.mapping.get()) do + if entity.valid and entity.name == "hs_holo_sign" then + local UN = entity.unit_number + if global.signs[UN] then + local Sign_Data = table.deepcopy(global.signs[UN]) + if index <= count then + item.set_blueprint_entity_tag(index, "Sign_Data", Sign_Data) + end + end + end + end +end +script.on_event(defines.events.on_player_setup_blueprint, on_player_setup_blueprint) + + +function restore_data_from_tags(entity, tags) + local Sign_Data = tags.Sign_Data + if not Sign_Data then return end + Copy_Sign_Data(entity, Sign_Data) +end + +local ghost_revived_event = function(event) + local entity = event.created_entity or event.entity + if not (entity and entity.valid) then return end + if entity.name ~= "hs_holo_sign" then return end + + local tags = event.tags + if not tags then return end + + restore_data_from_tags(entity, tags) +end +script.on_event(defines.events.on_robot_built_entity, ghost_revived_event) +script.on_event(defines.events.script_raised_revive, ghost_revived_event) + + +function on_post_entity_died(event) + local UN = event.unit_number + if not UN then return end + if global.signs[UN] then + local Sign_Data = table.deepcopy(global.signs[UN]) + if not Sign_Data then return end + local ghost = event.ghost + if not (ghost and ghost.valid) then return end + local tags = ghost.tags or {} + tags.Sign_Data = Sign_Data + ghost.tags = tags + end +end +script.on_event(defines.events.on_post_entity_died, on_post_entity_died) + +script.on_event(defines.events.on_pre_player_died, function(event) +local player = game.players[event.player_index] +global.last_death_tick = game.tick +end) + + + + + + + + + + +commands.add_command('hologram-turn-on', 'Turn ON all holograms', function(event) +local player = game.players[event.player_index] +if player.admin then + global.all_turned_off = false + UpdateAll() + end +end) +commands.add_command('hologram-turn-off', 'Turn OFF all holograms', function(event) +local player = game.players[event.player_index] +if player.admin then + global.all_turned_off = true + UpdateAll() + end +end) + + +function UpdateAll() +for UN, Sign_Data in pairs (global.signs) do + local entity = Sign_Data.entity + if entity and entity.valid then apply_holo_sign(Sign_Data) + else global.signs[UN]=nil end + end +end + + +script.on_nth_tick(60*2, function (event) +for UN, Sign_Data in pairs (global.signs) do + local entity = Sign_Data.entity + if entity and entity.valid then + local green = entity.get_merged_signal({type="virtual",name='signal-green'})==1 + local red = entity.get_merged_signal({type="virtual",name='signal-red'})==1 + if green then Sign_Data.state='right' end + if red then Sign_Data.state='left' end + if Sign_Data.input or green or red then apply_holo_sign(Sign_Data) end + else + global.signs[UN]=nil + end + end +end) + + + +-------------------------------------------------------------------------------------- + +-- INTERFACE + +-------------------------------------------------------------------------------------- +local interface = {} +function interface.refresh_all() +UpdateAll() +end +remote.add_interface( "holographic_signs", interface ) + + diff --git a/holographic_signs/data-final-fixes.lua b/holographic_signs/data-final-fixes.lua new file mode 100644 index 00000000..a9e9cef4 --- /dev/null +++ b/holographic_signs/data-final-fixes.lua @@ -0,0 +1,4 @@ + +if mods['space-exploration'] then + data.raw["container"]["hs_holo_sign"].collision_mask = data.raw["container"]["iron-chest"].collision_mask + end \ No newline at end of file diff --git a/holographic_signs/data-updates.lua b/holographic_signs/data-updates.lua new file mode 100644 index 00000000..2ff1ccaa --- /dev/null +++ b/holographic_signs/data-updates.lua @@ -0,0 +1,6 @@ + +if data.raw.technology['optics'] then + table.insert (data.raw.technology['optics'].effects,{type = "unlock-recipe", recipe = "hs_holo_sign"}) + data.raw.recipe["hs_holo_sign"].enabled = false + end + diff --git a/holographic_signs/data.lua b/holographic_signs/data.lua new file mode 100644 index 00000000..63da36e6 --- /dev/null +++ b/holographic_signs/data.lua @@ -0,0 +1,4 @@ +path = '__holographic_signs__/' +util = require("util") + +require "prototypes.holo_sign" diff --git a/holographic_signs/graphics/holobase.png b/holographic_signs/graphics/holobase.png new file mode 100644 index 00000000..73db55dd Binary files /dev/null and b/holographic_signs/graphics/holobase.png differ diff --git a/holographic_signs/graphics/hologram.png b/holographic_signs/graphics/hologram.png new file mode 100644 index 00000000..49bd76c6 Binary files /dev/null and b/holographic_signs/graphics/hologram.png differ diff --git a/holographic_signs/graphics/hologram_ico.png b/holographic_signs/graphics/hologram_ico.png new file mode 100644 index 00000000..d0574577 Binary files /dev/null and b/holographic_signs/graphics/hologram_ico.png differ diff --git a/holographic_signs/graphics/hr-holobase.png b/holographic_signs/graphics/hr-holobase.png new file mode 100644 index 00000000..faab8a77 Binary files /dev/null and b/holographic_signs/graphics/hr-holobase.png differ diff --git a/holographic_signs/info.json b/holographic_signs/info.json new file mode 100644 index 00000000..c37553a5 --- /dev/null +++ b/holographic_signs/info.json @@ -0,0 +1,11 @@ +{ + "name": "holographic_signs", + "version": "1.2.3", + "title": "Holographic Signs", + "author":"MFerrari", + "dependencies": ["base >= 1.1.0" ,"(?) space-exploration" ,"(?) shield-projector"], + "description": "This mod adds holographic signs to show configurable icon and text.", + "factorio_version": "1.1", + "homepage":"https://discord.gg/vDfm5tNEqK", + "contact": "Discord: MFerrari#6561" +} \ No newline at end of file diff --git a/holographic_signs/locale/en/config.cfg b/holographic_signs/locale/en/config.cfg new file mode 100644 index 00000000..f01dd03f --- /dev/null +++ b/holographic_signs/locale/en/config.cfg @@ -0,0 +1,64 @@ +holographic_sign=Holographic sign +hs_icon=Icon +hs_text=Text +hs_color=Text color +hs_add_tag=Add world map tag +hs_on_off=Turn off/on + +bt_holo_sign_textbox=Show/hide text box +bt_holo_sign_inputs=Show/hide input box +hs_input_box=Choose an input to print: +hs_plain_text=Plain text +bt_holo_sign_confirm=Confirm + +hs_hologram_image=Hologram image +hs_signal=Read circuit signal +hs_logistic=Count item on logistic +hs_research_progress=Research progress +hs_rockets_launched=Rockets launched +hs_connected_players=Connected players +hs_production=Item production +hs_consumption=Item consumption +hs_production_f=Fluid production +hs_production_p=Power production + +hs_player_casualties=Player casualties +hs_enemy_evolution=Enemy evolution +hs_kill_count=Kill count +hs_wind_speed=Wind speed +hs_day_time=Day time +hs_pollution=Pollution + +hs_research=Research +hs_timers=Timers +hs_rockets=Rockets +hs_production_m=Get production +hs_consumption_m=Get consumption +hs_players=Players + +hs_consumption_f=Fluid consumption +hs_consumption_p=Power consumption +hs_item_launched=Rocket item launched +hs_research_time_remaining=Time to finish the research +hs_total_time=Played time +hs_time_from_last_death=Time from last player death +hs_production_ratio=Item production/consumption ratio +hs_production_ratio_f=Fluid production/consumption ratio +hs_charge=Accumulator charge + +hs_warpdrive=Warp Drive Machine +hs_wdm_warping_in=Warping time +hs_wdm_time_on_planet=Time on planet +hs_native_evolution=Natives evolution +hs_planet_image=Planet image + +[item-name] +hs_holo_sign=Holographic sign + +[entity-name] +hs_holo_sign=Holographic sign + + +[mod-setting-name] +hs-opt-animation=Enable hologram animation +hs-opt-text-animation=Text animation \ No newline at end of file diff --git a/holographic_signs/locale/pt-BR/pt-BR.cfg b/holographic_signs/locale/pt-BR/pt-BR.cfg new file mode 100644 index 00000000..36ec9888 --- /dev/null +++ b/holographic_signs/locale/pt-BR/pt-BR.cfg @@ -0,0 +1,54 @@ +holographic_sign=Sinal holográfico +hs_icon=Ícone +hs_text=Texto +hs_color=Cor do texto +hs_add_tag=Incluir no mapa do mundo +hs_on_off=Desligar / Ligar +bt_holo_sign_textbox=Mostrar/ocultar quadro de texto +bt_holo_sign_inputs=Mostrar/ocultar quadro de entradas +hs_input_box=Escolha um valor de entrada +hs_plain_text=Texto plano +bt_holo_sign_confirm=Confirma +hs_hologram_image=Imagem holográfica +hs_signal=Ler sinal de circuito +hs_logistic=Contar item na logística +hs_research_progress=Progresso de pesquisa +hs_rockets_launched=Foguetes lançados +hs_connected_players=Jogadores conectados +hs_production=Produção de item +hs_consumption=Consumo de item +hs_production_f=Produção de fluído +hs_production_p=Produção de energia +hs_player_casualties=Morte de jogadores +hs_enemy_evolution=Evolução do inimigo +hs_kill_count=Contagem de mortes +hs_wind_speed=Velocidade do vento +hs_day_time=Hora do dia +hs_pollution=Poluição +hs_research=Pesquisa +hs_timers=Tempos +hs_rockets=Foguetes +hs_production_m=Produção +hs_consumption_m=Consumo +hs_players=Jogadores + +hs_consumption_f=Consumo de fluído +hs_consumption_p=Consumo de energia +hs_item_launched=Itens lançados +hs_research_time_remaining=Tempo para terminar pesquisa +hs_total_time=Tempo de jogo +hs_time_from_last_death=Tempo desde a última morte +hs_production_ratio=Taxa de produção/consumo de item +hs_production_ratio_f=Taxa de produção/consumo de fluído +hs_charge=Carga dos acumuladores +hs_planet_image=Imagem do planeta + +[item-name] +hs_holo_sign=Sinal holográfico + +[entity-name] +hs_holo_sign=Sinal holográfico + +[mod-setting-name] +hs-opt-animation=Ativar animação do holograma +hs-opt-text-animation=Animação do texto \ No newline at end of file diff --git a/holographic_signs/prototypes/holo_sign.lua b/holographic_signs/prototypes/holo_sign.lua new file mode 100644 index 00000000..9f5351c8 --- /dev/null +++ b/holographic_signs/prototypes/holo_sign.lua @@ -0,0 +1,140 @@ + +local hit_effects = require ("__base__/prototypes/entity/hit-effects") +local sounds = require("__base__/prototypes/entity/sounds") +local text_animation = settings.startup["hs-opt-text-animation"].value + +if mods['shield-projector'] then +data:extend({ +{ + type = "animation", + name = "hs_hologram_animated", + filename = "__shield-projector__/graphics/entity/shield-projector/hr/shield/wall-south.png", + scale = 0.5, + animation_speed = 0.3, + frame_count = 24, + width = 2816/4, + height = 3456/6, + shift = {0,0}, + line_length = 4 +}, +}) +end + + +local wrapper_flow_style = "compilatron_speech_bubble_wrapper" +if text_animation == 'No animation' then + wrapper_flow_style = "hs_speech_bubble_wrapper" + data.raw["gui-style"]["default"][wrapper_flow_style] ={type = "flow_style",effect = nil} + end + +local fade_in_out_ticks = data.raw['speech-bubble'].fade_in_out_ticks +if text_animation == 'Fast animation' then fade_in_out_ticks=5 end + +data:extend({ + +{ + type = "speech-bubble", + name = "hs-speech-bubble", + style = "compilatron_speech_bubble", + wrapper_flow_style = wrapper_flow_style, + fade_in_out_ticks = fade_in_out_ticks, + flags = {"not-on-map", "placeable-off-grid"} +}, + + + + { + type = "sprite", + name = "hs_hologram", + filename = path.."graphics/hologram.png", + priority = "extra-high", + width = 200, + height = 186, + }, + + + + { + type = "container", + --logistic_mode = "passive-provider", + name = "hs_holo_sign", + icon = path.."graphics/hologram_ico.png", + icon_size = 64, --icon_mipmaps = 4, + flags = {"placeable-player", "player-creation", "not-rotatable", "hide-alt-info"}, --"not-blueprintable" + minable = {mining_time = 0.2, result = "hs_holo_sign"}, + max_health = 100, + corpse = "lamp-remnants", + dying_explosion = "lamp-explosion", + collision_box = {{-0.15, -0.15}, {0.15, 0.15}}, + selection_box = {{-0.5, -0.5}, {0.5, 0.5}}, + damaged_trigger_effect = hit_effects.entity(), + vehicle_impact_sound = sounds.generic_impact, + inventory_size = 0, + open_sound = sounds.machine_open, + close_sound = sounds.machine_close, + resistances = + { + { + type = "fire", + percent = 80 + }, + { + type = "impact", + percent = 30 + } + }, + --circuit_wire_connection_point = circuit_connector_definitions["chest"].points, + circuit_wire_connection_point = data.raw.lamp['small-lamp'].circuit_wire_connection_point, + circuit_connector_sprites = data.raw.lamp['small-lamp'].circuit_connector_sprites, + circuit_wire_max_distance = data.raw.lamp['small-lamp'].circuit_wire_max_distance, + picture = + { + layers = + { + { + filename = path.."graphics/holobase.png", + priority = "extra-high", + width = 42, + height = 36, + frame_count = 1, + axially_symmetrical = false, + direction_count = 1, + shift = util.by_pixel(0,3), + hr_version = + { + filename = path.."graphics/hr-holobase.png", + priority = "high", + width = 83, + height = 70, + frame_count = 1, + axially_symmetrical = false, + direction_count = 1, + shift = util.by_pixel(0.25,3), + scale = 0.5 + } + }, + } + }, + }, + + + { + type = "item", + name = "hs_holo_sign", + icon = path.."graphics/hologram_ico.png", + icon_size = 64, --icon_mipmaps = 4, + subgroup = "circuit-network", + order = "a[items]-h[holo_sign]", + place_result = "hs_holo_sign", + stack_size= 100 + }, + + { + type = "recipe", + name = "hs_holo_sign", + energy_required = 2, + enabled = true, + ingredients = {{"iron-plate", 4}, {"electronic-circuit", 1}, {"small-lamp", 1}}, + result = "hs_holo_sign" + }, +}) diff --git a/holographic_signs/settings.lua b/holographic_signs/settings.lua new file mode 100644 index 00000000..15dce8d5 --- /dev/null +++ b/holographic_signs/settings.lua @@ -0,0 +1,21 @@ +local allowed_values = function() return {"Default", "Fast animation", "No animation"} end +data:extend({ + +{ + type = "bool-setting", + name = "hs-opt-animation", + setting_type = "runtime-global", + default_value = true, + order = "a" +}, + + { + type = "string-setting", + name = "hs-opt-text-animation", + setting_type = "startup", + default_value = "Default", + allowed_values = allowed_values(), + order = "h" + }, + +}) diff --git a/holographic_signs/speech-bubbles.lua b/holographic_signs/speech-bubbles.lua new file mode 100644 index 00000000..aaba189b --- /dev/null +++ b/holographic_signs/speech-bubbles.lua @@ -0,0 +1,49 @@ +-- v 1.2 -- custom hs-speech-bubble using unit_number 10/12/2021, + +function Entity_Speak(entity,text,seconds) +if entity and entity.valid then + local id = entity.unit_number + + if global.entity_speech[entity] then --- clears olf format + global.entity_speech[entity].bubble.destroy() + global.entity_speech[entity] = nil + end + + if global.entity_speech[id] then + global.entity_speech[id].bubble.destroy() + global.entity_speech[id] = nil + end + + local bubble = entity.surface.create_entity({ + name="hs-speech-bubble", + text=text, + position={0,0}, + source=entity }) + + global.entity_speech[id] = {} + global.entity_speech[id].bubble=bubble + if seconds and seconds>0 then global.entity_speech[id].tick=game.tick+seconds*60 end + end +end + + +script.on_nth_tick(61, function (event) +for k, entity_speech in pairs (global.entity_speech) do + local bubble = entity_speech.bubble + local tick = entity_speech.tick + if tick and game.tick >= tick then + bubble.destroy() + entity_speech=nil + end + end +end) + +function clear_speach_bubble(entity) +if entity and entity.valid then + local id = entity.unit_number + if global.entity_speech[id] and global.entity_speech[id].bubble and global.entity_speech[id].bubble.valid then + global.entity_speech[id].bubble.destroy() + global.entity_speech[id] = nil + end + end +end \ No newline at end of file diff --git a/holographic_signs/thumbnail.png b/holographic_signs/thumbnail.png new file mode 100644 index 00000000..bcaefb73 Binary files /dev/null and b/holographic_signs/thumbnail.png differ diff --git a/holographic_signs/utils.lua b/holographic_signs/utils.lua new file mode 100644 index 00000000..57849668 --- /dev/null +++ b/holographic_signs/utils.lua @@ -0,0 +1,186 @@ +require "util" +local format_number = util.format_number + +local format_time = util.formattime +function format_time_from_tick(ThatTick) + if game.tick > ThatTick then return format_time(game.tick-ThatTick) + else return format_time(ThatTick - game.tick) + end +end + +function format_t(tick) +return format_time(tick) +end + +function getDayTimeString(surface) + local daytime = surface.daytime + 0.5 + local dayminutes = math.floor(daytime * 24 * 60) % 60 + local dayhour = math.floor(daytime * 24 ) % 24 +return string.format("%02d:%02d", dayhour, dayminutes) +end + +function format_time_hour(tick) +return string.format("%d:%02d:%02d", math.floor(tick / 216000), math.floor(tick / 3600) % 60, math.floor(tick / 60) % 60) +end + + +function format_evolution(force) + return string.format("%.2f", math.floor(force.evolution_factor * 1000) / 10) +end + + +function shortnumberstring(number) + local steps = { + {1,""}, + {1e3,"k"}, + {1e6,"m"}, + {1e9,"g"}, + {1e12,"t"}, + } + for _,b in ipairs(steps) do + if b[1] <= number+1 then + steps.use = _ + end + end + local result = string.format("%.1f", number / steps[steps.use][1]) + if tonumber(result) >= 1e3 and steps.use < #steps then + steps.use = steps.use + 1 + result = string.format("%.1f", tonumber(result) / 1e3) + end + return result .. steps[steps.use][2] +end + +function my_format_number(number, maxed) +if not maxed then maxed=1000000000 end +local result +if number < maxed then result=format_number(number) --- + else result=shortnumberstring(number) end +return result +end + + +function get_gps_tag(position) +if get_gps_tag then + return '[gps='..math.floor(position.x)..','..math.floor(position.y)..']' + else return '' + end +end + + + +-------------------------------------------------------------------------------------- +function iif( cond, val1, val2 ) + if cond then + return val1 + else + return val2 + end +end + + +--for k,v in Sort_a_Table(your_table, function(t,a,b) return t[b] > t[a] end) do +function Sort_a_Table(t, order) + -- collect the keys + local keys = {} + for k in pairs(t) do keys[#keys+1] = k end + + -- if order function given, sort by it by passing the table and keys a, b, + -- otherwise just sort the keys + if order then + table.sort(keys, function(a,b) return order(t, a, b) end) + else + table.sort(keys) + end + + -- return the iterator function + local i = 0 + return function() + i = i + 1 + if keys[i] then + return keys[i], t[keys[i]] + end + end +end + +-------------------------------------------------------------------------------------- +function add_list(list, obj) + -- to avoid duplicates... + for i, obj2 in pairs(list) do + if obj2 == obj then + return(false) + end + end + table.insert(list,obj) + return(true) +end + +-------------------------------------------------------------------------------------- +function del_list(list, obj) + for i, obj2 in pairs(list) do + if obj2 == obj then + table.remove( list, i ) + return(true) + end + end + return(false) +end +-------------------------------------------------------------------------------------- +function del_list2(list, list2) + for i, obj2 in pairs(list2) do del_list(list, obj2) end +end +-------------------------------------------------------------------------------------- +function in_list(list, obj) + for k, obj2 in pairs(list) do + if obj2 == obj then + return(k) + end + end + return(nil) +end + + + +function Log(what) +game.write_file("hs.log", serpent.block(what), true) +end + +function dLog(what) +log(serpent.block(what)) +end + + + + + +-- research utils +function is_multilevel(technology) + if technology.object_name == "LuaTechnology" then + technology = technology.prototype + end + return technology.level ~= technology.max_level +end +--- @param technology LuaTechnology +--- @param level uint +--- @return double +function get_research_progress(technology, level) + local force = technology.force + local current_research = force.current_research + if current_research and current_research.name == technology.name then + if not is_multilevel(technology) or technology.level == level then + return force.research_progress + else + return 0 + end + else + return force.get_saved_technology_progress(technology) or 0 + end +end +function get_research_unit_count(technology, level) + local formula = technology.research_unit_count_formula + if formula then + local level = level or technology.level + return math.floor(game.evaluate_expression(formula, { l = level, L = level })) + else + return math.floor(technology.research_unit_count) --[[@as double]] + end +end \ No newline at end of file diff --git a/mod-list.json b/mod-list.json index 523feae1..272f7901 100644 --- a/mod-list.json +++ b/mod-list.json @@ -453,6 +453,11 @@ "enabled": true }, + { + "name": "holographic_signs", + "enabled": true + }, + { "name": "immersive-sounds", "enabled": true diff --git a/mod-settings.dat b/mod-settings.dat index 013ca32d..2797594d 100644 Binary files a/mod-settings.dat and b/mod-settings.dat differ diff --git a/zzzparanoidal/prototypes/micro-final-fix.lua b/zzzparanoidal/prototypes/micro-final-fix.lua index b8c1ba6c..76ccfd48 100644 --- a/zzzparanoidal/prototypes/micro-final-fix.lua +++ b/zzzparanoidal/prototypes/micro-final-fix.lua @@ -1411,6 +1411,12 @@ bobmods.lib.tech.add_recipe_unlock("nitinol-processing", "angels-nitinol-pipe-to --Для сборщика электроники нужны фиол. манипуляторы (AKMF) bobmods.lib.tech.add_prerequisite("electronics-machine-3", "turbo-inserter") +--добавление табличек holographic_signs в технологию (AKMF) +if data.raw.recipe["hs_holo_sign"] then + data.raw["recipe"]["hs_holo_sign"].enabled = false + bobmods.lib.tech.add_recipe_unlock("circuit-network", "hs_holo_sign") +end + --Убрана левая печь из электо печи для сплавов (AKMF) bobmods.lib.recipe.remove_ingredient("electric-mixing-furnace", "electric-chemical-furnace") KaoExtended.recipe.addtorecipe("electric-mixing-furnace", {"electric-furnace", 1}) \ No newline at end of file