393 lines
14 KiB
Lua

require("util")
require("utils")
require("particles")
local ticks_1_s = 60
-- CUSTOM EVENT HANDLING --
-- if your mod creates the stage 1 construction site via script, you should add the "raise_built=true" to your create_entity, so here
-- it will fire the script_raised_built event
-- A custom event is raised upon each finished construction stage, named "on_silo_stage_finished"
--(remote interface is lower in the file, there I describe how to subscribe to my event)
local on_silo_stage_finished = script.generate_event_name() --uint returns event.created_entity
function ModSetup()
ReadRunTimeSettings(event)
if global.rsc_silo_under_construction==nil then global.rsc_silo_under_construction={} end
global.automated_forces = global.automated_forces or {}
global.st_insert_material_work = settings.startup["rsc-st-work-for-insert-material"].value
global.st_remove_stone_work = settings.startup["rsc-st-work-for-remove-stone"].value
global.st_not_removable_silo = settings.startup["rsc-st-not-removable-silo"].value
global.st_not_removable_site = settings.startup["rsc-st-not-removable-site"].value
global.st_dont_place_tiles = settings.startup["rsc-st-dont-place-tiles"].value
global.st_enable_se_cargo = false
global.st_enable_se_probe = false
if settings.startup["rsc-st-enable-se-cargo-silo"] then global.st_enable_se_cargo =settings.startup["rsc-st-enable-se-cargo-silo"].value end
if settings.startup["rsc-st-enable-se-probe-silo"] then global.st_enable_se_probe =settings.startup["rsc-st-enable-se-probe-silo"].value end
for f=1, #game.forces do
local force = game.forces[f]
if force and force.technologies then
if force.technologies['rocket-silo'] and force.technologies['rocket-silo'].researched then
force.recipes['rsc-excavation-site'].enabled = true
end
if force.technologies['se-rocket-launch-pad'] and force.technologies['se-rocket-launch-pad'].researched then
if global.st_enable_se_cargo then force.recipes['rsc-serlp-excavation-site'].enabled=true end
force.recipes['se-rocket-launch-pad'].enabled = not global.st_enable_se_cargo
end
if force.technologies['se-space-probe'] and force.technologies['se-space-probe'].researched then
if global.st_enable_se_probe then force.recipes['rsc-sesprs-excavation-site'].enabled=true end
force.recipes['se-space-probe-rocket-silo'].enabled = not global.st_enable_se_probe
end
end
end
end
function ReadRunTimeSettings(event)
global.st_only_in_alt_mode = settings.global["rsc-only-in-alt-mode"].value
end
script.on_event(defines.events.on_runtime_mod_setting_changed, ReadRunTimeSettings)
function On_Init()
ModSetup()
end
function on_configuration_changed(data)
ModSetup()
end
script.on_configuration_changed(on_configuration_changed)
script.on_init(On_Init)
local function FillWith(surface,position,area,withwhat)
if (not global.st_dont_place_tiles) and (not remote.interfaces["warptorio2"]) then
if remote.interfaces["space-exploration"] then
local Zone = remote.call("space-exploration", "get_zone_from_name", {zone_name = surface.name})
if Zone then
local zone_index = Zone.index
local is_space = remote.call("space-exploration", "get_zone_is_space", {zone_index = zone_index})
if is_space then return end
end
end
local solo = {}
local X = position.x
local Y = position.y
local x1,x2 = X-area , X+area
local y1,y2 = Y-area , Y+area
for y=y1,y2 do
for x=x1,x2 do
table.insert(solo, {name=withwhat, position={x=x, y=y}})
end
end
if #solo>0 then
surface.set_tiles(solo)
end
end
end
local function CallFrenzyAttack(target)
if (target and target.valid) then
if target.surface.map_gen_settings and target.surface.map_gen_settings.autoplace_controls and
target.surface.map_gen_settings.autoplace_controls["enemy-base"] and target.surface.map_gen_settings.autoplace_controls["enemy-base"].size>0 then
local Min = 30
local Max = 50
local Dist = 400
local aliens = math.random(Min,Max)
local spawn = target.surface.find_entities_filtered({type = "unit-spawner",limit=1,position=target.position, radius=Dist})
if #spawn>0 then
local force = spawn[1].force
local sent = target.surface.set_multi_command({
command = {type=defines.command.attack_area, destination=target.position, radius=50, distraction = defines.distraction.by_anything },
unit_count = aliens,
force = force,
unit_search_distance = Dist,
})
end
end
end
end
function upgrade_construction_site(silo_data)
local silo=silo_data.silo
if silo and silo.valid then
local name=silo.name
local upgrade_to
local last_user = silo.last_user
local final_building = 'rocket-silo' -- default
if silo_data.final_building ~= nil then final_building=silo_data.final_building end
local work = global.st_insert_material_work
local position=silo.position
local surface=silo.surface
local force=silo.force
if name=='rsc-silo-stage1' then upgrade_to='rsc-silo-stage2'
elseif name=='rsc-silo-stage2' then upgrade_to='rsc-silo-stage3' work = global.st_remove_stone_work
elseif name=='rsc-silo-stage3' then upgrade_to='rsc-silo-stage4' FillWith(surface,position,5,'concrete')
elseif name=='rsc-silo-stage4' then upgrade_to='rsc-silo-stage5'
elseif name=='rsc-silo-stage5' then upgrade_to='rsc-silo-stage6' FillWith(surface,position,6,'concrete') FillWith(surface,position,5,'refined-hazard-concrete-left')
elseif name=='rsc-silo-stage6' then upgrade_to=final_building
elseif name=='rsc-silo-stage1-serlp' then upgrade_to='rsc-silo-stage2-serlp'
elseif name=='rsc-silo-stage2-serlp' then upgrade_to='rsc-silo-stage3-serlp' work = global.st_remove_stone_work
elseif name=='rsc-silo-stage3-serlp' then upgrade_to='rsc-silo-stage4-serlp' FillWith(surface,position,6,'concrete')
elseif name=='rsc-silo-stage4-serlp' then upgrade_to='rsc-silo-stage5-serlp'
elseif name=='rsc-silo-stage5-serlp' then upgrade_to='rsc-silo-stage6-serlp' FillWith(surface,position,7,'concrete') FillWith(surface,position,6,'refined-hazard-concrete-left')
elseif name=='rsc-silo-stage6-serlp' then upgrade_to=final_building
elseif name=='rsc-silo-stage1-sesprs' then upgrade_to='rsc-silo-stage2-sesprs'
elseif name=='rsc-silo-stage2-sesprs' then upgrade_to='rsc-silo-stage3-sesprs' work = global.st_remove_stone_work
elseif name=='rsc-silo-stage3-sesprs' then upgrade_to='rsc-silo-stage4-sesprs'
elseif name=='rsc-silo-stage4-sesprs' then upgrade_to='rsc-silo-stage5-sesprs'
elseif name=='rsc-silo-stage5-sesprs' then upgrade_to='rsc-silo-stage6-sesprs'
elseif name=='rsc-silo-stage6-sesprs' then upgrade_to=final_building end
silo.destroy()
local new_stage = surface.create_entity{name = upgrade_to, position = position, force=force, raise_built=true}
if math.random(0,1)==0 then CallFrenzyAttack(new_stage) end
if last_user then new_stage.last_user = last_user end
if upgrade_to~=final_building then
local silo_data = {silo=new_stage,bar_back=nil,progress_bar=nil,work_value=work,final_building=final_building}
table.insert (global.rsc_silo_under_construction,silo_data)
check_construction_site(silo_data)
if global.st_not_removable_site then new_stage.minable=false end
else
if global.st_not_removable_silo then new_stage.minable=false end
end
script.raise_event(on_silo_stage_finished, {created_entity = new_stage})
end
end
function check_construction_site(silo_data)
local entity=silo_data.silo
local progress=entity.products_finished
local max_progress=silo_data.work_value
if progress>=max_progress then
entity.active = false
if entity.get_output_inventory().get_item_count()<1 or in_list(global.automated_forces,entity.force.name) then
upgrade_construction_site(silo_data)
return
end
end
local visible_to
if not in_list(global.automated_forces,entity.force.name) then visible_to = {entity.force} end
local background = silo_data.bar_back
if not background then
background = rendering.draw_line
{
color = {r = 1, b = 1, g = 1},
width = 10,
from = entity,
from_offset = {-33/32, 1},
to = entity,
to_offset = {33/32, 1},
surface = entity.surface,
forces = visible_to,
only_in_alt_mode = global.st_only_in_alt_mode
}
silo_data.bar_back = background
end
local progress_bar = silo_data.progress_bar
if not progress_bar then
progress_bar = rendering.draw_line
{
color = {r = 0, g = 1, b = 0},
width = 8,
from = entity,
from_offset = {-1, 1},
to = entity,
to_offset = {1, 1},
surface = entity.surface,
forces = visible_to,
only_in_alt_mode = global.st_only_in_alt_mode
}
silo_data.progress_bar = progress_bar
end
rendering.set_to(silo_data.progress_bar, entity, {(2 * (progress / max_progress)) - 1, 1})
if (entity.is_crafting() and entity.crafting_progress>0 and entity.crafting_progress<1) or (not visible_to) then
if (entity.energy>0 or (not visible_to)) then
if (string.find(entity.name, 'stage1') or string.find(entity.name, 'stage3')) then
if math.random(5)==1 then create_remnants_particles(entity.surface, 8 + math.random(20), get_random_pos_near(entity.position,3),2)
elseif math.random(3)==1 then create_stone_particles(entity.surface, 8 + math.random(30), get_random_pos_near(entity.position,3),2) end
end
for x=1,2 do
local p = get_random_pos_near(entity.position,2)
entity.surface.create_trivial_smoke{name='fire-smoke-on-adding-fuel', position=p}
entity.surface.create_trivial_smoke{name='turbine-smoke', position=p}
end
end
end
end
script.on_nth_tick(ticks_1_s, function (event)
for k, silo_data in pairs (global.rsc_silo_under_construction) do
local silo = silo_data.silo
if silo and silo.valid then
check_construction_site(silo_data)
else
table.remove (global.rsc_silo_under_construction,k)
end
end
end)
function On_Built(event)
local ent = event.created_entity
if not ent then ent = event.entity end
local sufix = ''
if ent and ent.valid then
if string.sub(ent.name,1,15) == 'rsc-silo-stage1' then
local surface = ent.surface
local final_building = 'rocket-silo'
local work_value=global.st_remove_stone_work
if ent.name == 'rsc-silo-stage1-serlp' then final_building = 'se-rocket-launch-pad' sufix='-serlp'
elseif ent.name == 'rsc-silo-stage1-sesprs' then final_building = 'se-space-probe-rocket-silo' sufix='-sesprs'
end
-- if space explorarion mod present - if in orbit, then construction starts in stage 4 - no excavation required
if remote.interfaces["space-exploration"] then
local Zone = remote.call("space-exploration", "get_zone_from_name", {zone_name = surface.name})
if Zone then
local zone_index = Zone.index
local is_space = remote.call("space-exploration", "get_zone_is_space", {zone_index = zone_index})
if is_space then
local position = ent.position
local force=ent.force
local player_index=event.player_index
ent.destroy()
local stage4 = 'rsc-silo-stage4' .. sufix
ent=surface.create_entity{name=stage4, force=force, position = position, raise_built=true}
if player_index then ent.last_user = game.players[player_index] end
work_value=global.st_insert_material_work
end
end
end
local silo_data =
{
silo=ent,
bar_back=nil,
progress_bar=nil,
work_value=work_value,
final_building=final_building
}
table.insert (global.rsc_silo_under_construction,silo_data)
check_construction_site(silo_data)
if global.st_not_removable_site then ent.minable=false end
end
end
end
--local build_events = {defines.events.on_built_entity, defines.events.on_robot_built_entity, defines.events.script_raised_built}
local filters = {{filter = "name", name = "rsc-silo-stage1"}, {filter = "name", name = "rsc-silo-stage1-serlp"}, {filter = "name", name = "rsc-silo-stage1-sesprs"}}
script.on_event(defines.events.on_built_entity, On_Built, filters)
script.on_event(defines.events.on_robot_built_entity, On_Built, filters)
script.on_event(defines.events.script_raised_built, On_Built,filters)
script.on_event(defines.events.script_raised_revive, On_Built,filters)
function on_entity_cloned(event)
local destination = event.destination
local list = {}
if string.sub(destination.name,1,14)=='rsc-silo-stage' then
for k,silo_data in pairs (global.rsc_silo_under_construction) do
if silo_data.silo == event.source then
global.rsc_silo_under_construction[k].silo = destination
global.rsc_silo_under_construction[k].bar_back=nil
global.rsc_silo_under_construction[k].progress_bar=nil
break
end
end
end
end
script.on_event(defines.events.on_entity_cloned, on_entity_cloned)
local function upgrade_silos_now(force_name)
local tabcopy = table.deepcopy(global.rsc_silo_under_construction)
local force
if force_name then force = game.forces[force_name] end
for k, silo_data in pairs (tabcopy) do
if (not force_name) or (force and silo_data.silo.force == force) then
upgrade_construction_site(silo_data)
end
end
end
-- INTERFACE --
--------------------------------------------------------------------------------------
local interface = {}
-- /c remote.call("RocketSiloCon","UpgradeConstruction")
function interface.UpgradeConstruction()
upgrade_silos_now()
end
-- /c remote.call("RocketSiloCon","UpgradeForceConstruction","player")
function interface.UpgradeForceConstruction(force_name)
upgrade_silos_now(force_name)
end
function interface.add_automated_force(force_name)
add_list(global.automated_forces, force_name)
end
--[[ HOW TO subscribe to my custom event:
script.on_event(remote.call("RocketSiloCon", "get_on_silo_stage_finished"), function(event)
--do your stuff
end)
WARNING: this has to be done within on_init and on_load, otherwise the game will error about the remote.call
returns {created_entity = new_stage}
if your dependency on my mod is optional, remember to check if the remote interface exists before calling it:
if remote.interfaces["RocketSiloCon"] then
--interface exists
end]]
function interface.get_on_silo_stage_finished()
return on_silo_stage_finished
end
-- Returns :
-- event.created_entity = The new entity created (next stage building)
remote.add_interface("RocketSiloCon", interface )