From c84ab187b6d82720d25f65622a2235706d396267 Mon Sep 17 00:00:00 2001 From: Aleksei-bird Date: Fri, 7 Jun 2024 19:00:00 +0300 Subject: [PATCH] =?UTF-8?q?#69=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=87?= =?UTF-8?q?=D0=B5=D0=BA=20holographic=5Fsigns=20=D0=B2=20=D1=82=D0=B5?= =?UTF-8?q?=D1=85=D0=BD=D0=BE=D0=BB=D0=BE=D0=B3=D0=B8=D1=8E=20#73=20=D0=92?= =?UTF-8?q?=D1=8B=D1=80=D0=B5=D0=B7=D0=B0=D0=BD=D0=B0=20=D0=BC=D0=B5=D1=85?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=BA=D0=B0=20=D0=BF=D0=BE=D1=82=D1=80=D0=B5?= =?UTF-8?q?=D0=B1=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BE=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D1=85=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BD=D0=B2=D0=B5=D0=B5=D1=80=D0=BE=D0=B2=20=D0=B8?= =?UTF-8?q?=20=D1=82=D1=80=D1=83=D0=B1=20=D0=BF=D1=80=D0=B8=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D1=89=D0=B5=D0=BD=D0=B8=D0=B8=20=D1=81=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D1=85=D0=B4=D0=BB=D0=B8=D0=BD=D0=BD=D1=8B=D1=85=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BD=D0=B2=D0=B5=D0=B5=D1=80=D0=BE=D0=B2=20=D0=B8?= =?UTF-8?q?=20=D1=82=D1=80=D1=83=D0=B1=20=20=20=20=20=D0=92=D1=8B=D1=80?= =?UTF-8?q?=D0=B5=D0=B7=D0=B0=D0=BD=D1=8B=20=D1=81=D0=B2=D1=8F=D0=B7=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B5=20=D1=81=20=D0=BD=D0=B5=D0=B9=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D0=B8=20=20=20=20=20=D0=A3=D0=B1?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=20=D1=84=D0=BB=D0=B0=D0=B3=20not-deconstruct?= =?UTF-8?q?able=20=D1=81=D0=BE=20=D1=81=D0=B2=D0=B5=D1=80=D1=85=D0=B4?= =?UTF-8?q?=D0=BB=D0=B8=D0=BD=D0=BD=D1=8B=D1=85=20=D0=BA=D0=BE=D0=BD=D0=B2?= =?UTF-8?q?=D0=B5=D0=B5=D1=80=D0=BE=D0=B2=20=D0=B8=20=D1=82=D1=80=D1=83?= =?UTF-8?q?=D0=B1,=20=D1=87=D1=82=D0=BE=20=D1=83=D0=BF=D1=80=D0=BE=D1=89?= =?UTF-8?q?=D0=B0=D0=B5=D1=82=20=D0=B8=D1=85=20=D0=B8=D1=81=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D1=81?= =?UTF-8?q?=20=D0=B4=D1=80=D0=BE=D0=BD=D0=B0=D0=BC=D0=B8=20=20=20=20=20?= =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=BE=20=D0=B0=D0=BD?= =?UTF-8?q?=D0=B3=D0=BB=D0=B8=D0=B9=D1=81=D0=BA=D0=BE=D0=B5=20=D0=BE=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D0=BD=D0=B8=D0=B5=20=D1=81=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D1=85=D0=B4=D0=BB=D0=B8=D0=BD=D0=BD=D1=8B=D1=85=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BD=D0=B2=D0=B5=D0=B5=D1=80=D0=BE=D0=B2=20=D0=B8=20=D1=82?= =?UTF-8?q?=D1=80=D1=83=D0=B1=20(=D1=80=D1=83=D1=81=D1=81=D0=BA=D0=BE?= =?UTF-8?q?=D0=B5=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B9?= =?UTF-8?q?=20=D0=BD=D0=B5=20=D1=82=D1=80=D0=B5=D0=B1=D1=83=D0=B5=D1=82)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Subterranean/control.lua | 2 + Subterranean/data-updates.lua | 4 +- Subterranean/locale/en/locale.cfg | 20 +- Subterranean/prototypes/entity.lua | 8 +- Subterranean/settings.lua | 2 + holographic_signs/changelog.txt | 126 ++ holographic_signs/control.lua | 1076 ++++++++++++++++++ holographic_signs/data-final-fixes.lua | 4 + holographic_signs/data-updates.lua | 6 + holographic_signs/data.lua | 4 + holographic_signs/graphics/holobase.png | Bin 0 -> 3631 bytes holographic_signs/graphics/hologram.png | Bin 0 -> 25414 bytes holographic_signs/graphics/hologram_ico.png | Bin 0 -> 9074 bytes holographic_signs/graphics/hr-holobase.png | Bin 0 -> 11529 bytes holographic_signs/info.json | 11 + holographic_signs/locale/en/config.cfg | 64 ++ holographic_signs/locale/pt-BR/pt-BR.cfg | 54 + holographic_signs/prototypes/holo_sign.lua | 140 +++ holographic_signs/settings.lua | 21 + holographic_signs/speech-bubbles.lua | 49 + holographic_signs/thumbnail.png | Bin 0 -> 27439 bytes holographic_signs/utils.lua | 186 +++ mod-list.json | 5 + mod-settings.dat | Bin 120351 -> 120432 bytes zzzparanoidal/prototypes/micro-final-fix.lua | 6 + 25 files changed, 1772 insertions(+), 16 deletions(-) create mode 100644 holographic_signs/changelog.txt create mode 100644 holographic_signs/control.lua create mode 100644 holographic_signs/data-final-fixes.lua create mode 100644 holographic_signs/data-updates.lua create mode 100644 holographic_signs/data.lua create mode 100644 holographic_signs/graphics/holobase.png create mode 100644 holographic_signs/graphics/hologram.png create mode 100644 holographic_signs/graphics/hologram_ico.png create mode 100644 holographic_signs/graphics/hr-holobase.png create mode 100644 holographic_signs/info.json create mode 100644 holographic_signs/locale/en/config.cfg create mode 100644 holographic_signs/locale/pt-BR/pt-BR.cfg create mode 100644 holographic_signs/prototypes/holo_sign.lua create mode 100644 holographic_signs/settings.lua create mode 100644 holographic_signs/speech-bubbles.lua create mode 100644 holographic_signs/thumbnail.png create mode 100644 holographic_signs/utils.lua 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 0000000000000000000000000000000000000000..73db55dd488c115167eccec34daa4c12f6c9be63 GIT binary patch literal 3631 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 BDnbAN literal 0 HcmV?d00001 diff --git a/holographic_signs/graphics/hologram.png b/holographic_signs/graphics/hologram.png new file mode 100644 index 0000000000000000000000000000000000000000..49bd76c69759637cd85f7cef7a7f7851f74afe26 GIT binary patch literal 25414 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 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 0000000000000000000000000000000000000000..bcaefb737cddb3b939583436dfde87fb682418b3 GIT binary patch literal 27439 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 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 013ca32d499ef90321a6883b13df5f52b8ee69f3..2797594d4b749ab7fd4660a99bf0e173789ab443 100644 GIT binary patch delta 98 zcmbQghW*1D_6bsq%NnJ(N;4|+3W;VE>*g1f=$52bl;|erW#%SMcI*?8W_L+VODxSP wVc;t&%`3^wP1Q}$$xlkmVP&|sJ%E>yaWXelA4tn&MR5^E#_j$K7%!Lt0DC4N;Q#;t delta 48 zcmeychJF4T_6bsqOBNOurgfTUeC+OIC=Y`1&rrR E0i|CNQ~&?~ 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