From 87c2c17d72f37ef6288e38dafa71b5659ffe830e Mon Sep 17 00:00:00 2001 From: Wyrrrd Date: Wed, 21 Apr 2021 10:28:24 +0200 Subject: [PATCH] Scan rework, car fix & multislot fix - only scanning for forces with connected players - only scanning on init, updating with entities when they are built/removed - no alerts for cars without guns - added multislot behaviour --- changelog.txt | 11 +++-- control.lua | 126 +++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 116 insertions(+), 21 deletions(-) diff --git a/changelog.txt b/changelog.txt index 1b3d16b..ac34788 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,12 +1,15 @@ --------------------------------------------------------------------------------------------------- Version: 1.1.5 -Date: 2021-04-19 +Date: 2021-04-21 Features: - - Added config option to change behaviour on multiple ammo slots (for cars) + - Added config option to change behaviour on multiple ammo slots (mainly for cars) Bugfixes: - - Fixed only checking for first ammo slot in cars + - Fixed only checking first ammo slot in cars + - Fixed modded cars without guns causing ammo empty alerts (AAI) Optimisations: - - Theoretical performance improvement by not scanning surfaces twice anymore (once for turrets and once for cars) + - Only scanning surfaces for forces with connected players + - Only scanning surfaces on init now, updating by single entities as they are build or removed + - Only scanning surfaces once instead of twice (once for turrets and once for cars) --------------------------------------------------------------------------------------------------- Version: 1.1.4 Date: 2021-04-02 diff --git a/control.lua b/control.lua index 524e3ba..498c1d6 100644 --- a/control.lua +++ b/control.lua @@ -1,6 +1,18 @@ --control.lua --This mod scans the map for cars and gun-turrets and places alerts when they are low on ammo. +--util functions + +function table_is_empty(table) + for _,_ in pairs(table) do + return false + end + return true +end + + +--local functions + local get_ammo_flags = { --Applies mode to inventory, calculates and returns respective inventory flags ["added"] = function (inventory,player_threshold) @@ -55,25 +67,83 @@ local get_ammo_flags = { end } +local function add_entity_to_list(event) + --Whenever an ammo-turret or car type entity is built, add it to the global table. + local index = event.created_entity.surface.name.."_"..event.created_entity.force.name + if global.ammo_entities[index] then + table.insert(global.ammo_entities[index], event.created_entity) + end +end -script.on_init(function (event) +local function remove_entity_from_list(event) + --Whenever an ammo-turret or car type entity dies / is mined, remove it from the global table. + local index = event.entity.surface.name.."_"..event.entity.force.name + if global.ammo_entities[index] then + for i,entity in pairs(global.ammo_entities[index]) do + if (entity == event.entity) then + table.remove(global.ammo_entities[index], i) + break + end + end + end +end + +local function add_force_to_list(event) + --Whenever a player of an unscanned force joins the game or a force is created, add all ammo-turret or car type entities of that force to the global table. + local player, force + if event.player_index then + player = game.get_player(event.player_index) + force = player.force + elseif event.force then + force = event.force + if force.connected_players then + player = force.connected_players[1] + end + end + + if player and force and not global.ammo_entities[player.surface.name.."_"..force.name] then + for _,surface in pairs(game.surfaces) do + global.ammo_entities[surface.name.."_"..force.name] = surface.find_entities_filtered{type = {"ammo-turret","car"}, force = force, to_be_deconstructed = false} + end + end +end + +local function remove_force_from_list(event) + --Whenever the last player of a force leaves the game or forces are merged, remove all entities of that force from the global table. + local force + local param = {} + if event.player_index and event.force then + param.player_index = event.player_index + add_force_to_list(param) + force = event.force + elseif event.player_index then + force = game.get_player(event.player_index).force + elseif event.force then + force = event.force + elseif event.source and event.destination then + param.force = event.destination + add_force_to_list(param) + force = source + end + + if force and not force.connected_players then + for surface_name,_ in pairs(game.surfaces) do + global.ammo_entities[surface_name.."_"..force.name] = nil + end + end +end + +local function init_list() -- index init global.ammo_entities = {} -end) - -script.on_configuration_changed(function (event) - -- index init fix - global.ammo_entities = {} -end) - -script.on_nth_tick(3600, function (event) - --Every minute the surface is rescanned for car and ammo-turret type entities. This is stored in a global table. - for index,surface in pairs(game.surfaces) do - global.ammo_entities[index] = surface.find_entities_filtered{type = {"ammo-turret","car"}} + local param = {} + for _,force in pairs(game.forces) do + param.force = force + add_force_to_list(param) end -end) +end -script.on_nth_tick(600, function (event) +local function generate_alerts() --Every 10 seconds recheck and give alerts to players for car and ammo-turret entities on the same force as them. for _,player in pairs(game.connected_players) do @@ -81,7 +151,7 @@ script.on_nth_tick(600, function (event) local car_enabled = player.mod_settings["gun-turret-alerts-car-enabled"].value local mode = player.mod_settings["gun-turret-alerts-mode"].value local player_threshold = player.mod_settings["gun-turret-alerts-threshold"].value - local ammo_entities = global.ammo_entities[player.surface.name] + local ammo_entities = global.ammo_entities[player.surface.name.."_"..player.force.name] if ammo_entities then for _,entity in pairs(ammo_entities) do @@ -91,7 +161,7 @@ script.on_nth_tick(600, function (event) local inventory if turret_enabled and entity.type == "ammo-turret" then inventory = entity.get_inventory(defines.inventory.turret_ammo) - elseif car_enabled and entity.type == "car" --[[and entity.prototype.guns]] then + elseif car_enabled and entity.type == "car" and not table_is_empty(entity.prototype.guns) then inventory = entity.get_inventory(defines.inventory.car_ammo) end @@ -117,4 +187,26 @@ script.on_nth_tick(600, function (event) end end end -end) \ No newline at end of file +end + + +-- Event handlers + +script.on_init(init_list) +script.on_configuration_changed(init_list) + +script.on_event(defines.events.on_player_joined_game, add_force_to_list) +script.on_event(defines.events.on_player_left_game, remove_force_from_list) +script.on_event(defines.events.on_player_changed_force, remove_force_from_list) + +script.on_event(defines.events.on_force_created, add_force_to_list) +script.on_event(defines.events.on_forces_merged, remove_force_from_list) + +script.on_event(defines.events.on_built_entity, add_entity_to_list, {{filter="type", type = "ammo-turret"},{filter="type", type = "car"}}) +script.on_event(defines.events.on_robot_built_entity, add_entity_to_list, {{filter="type", type = "ammo-turret"},{filter="type", type = "car"}}) + +script.on_event(defines.events.on_player_mined_entity, remove_entity_from_list, {{filter="type", type = "ammo-turret"},{filter="type", type = "car"}}) +script.on_event(defines.events.on_robot_mined_entity, remove_entity_from_list, {{filter="type", type = "ammo-turret"},{filter="type", type = "car"}}) +script.on_event(defines.events.on_entity_died, remove_entity_from_list, {{filter="type", type = "ammo-turret"},{filter="type", type = "car"}}) + +script.on_nth_tick(600, generate_alerts) \ No newline at end of file