274 lines
10 KiB
Lua
274 lines
10 KiB
Lua
--[[ Copyright (c) 2020 robot256 (MIT License)
|
|
* Project: Robot256's Library
|
|
* File: replace_carriage.lua
|
|
* Description: Replaces one Carriage Entity with a new one of the
|
|
* same type and different entity-name. Preserves as many properties
|
|
* of the original as possible.
|
|
* Parameters: carriage: locomotive or wagon entity to be replaced)
|
|
* newName: name of entity to replace it)
|
|
* raiseBuilt (optional): whether or not to issue script_raised_built when done creating the new carriage
|
|
* raiseDestroy (optional): whether or not to issue script_raised_destroy when destroying the old carriage
|
|
* flip (optional): whether to rotate the replacement carriage 180 degrees relative to the original
|
|
* Returns: newCarriage entity if successful, nil if unsuccessful
|
|
* Dependencies: saveGrid,
|
|
* restoreGrid,
|
|
* saveBurner,
|
|
* restoreBurner,
|
|
* saveItemRequestProxy,
|
|
* saveInventoryStacks,
|
|
* insertInventoryStacks,
|
|
* saveFilters,
|
|
* restoreFilters,
|
|
* spillStacks
|
|
--]]
|
|
|
|
local saveRestoreLib = require("__Robot256Lib__/script/save_restore")
|
|
|
|
|
|
local function replaceCarriage(carriage, newName, raiseBuilt, raiseDestroy, flip)
|
|
|
|
-- Save basic parameters
|
|
local position = carriage.position
|
|
local force = carriage.force
|
|
local surface = carriage.surface
|
|
local orientation = carriage.orientation
|
|
local backer_name = carriage.backer_name
|
|
local color = carriage.color
|
|
local health = carriage.health
|
|
local player_driving = carriage.get_driver()
|
|
local last_user = carriage.last_user
|
|
local minable = carriage.minable
|
|
local destructible = carriage.destructible
|
|
local operable = carriage.operable
|
|
local rotatable = carriage.rotatable
|
|
local enable_logistics_while_moving = carriage.enable_logistics_while_moving
|
|
|
|
-- Save deconstruction request by any force
|
|
local deconstruction_request = nil
|
|
for _,f in pairs(game.forces) do
|
|
if carriage.to_be_deconstructed(f) then
|
|
deconstruction_request = f
|
|
break
|
|
end
|
|
end
|
|
|
|
-- Save GUI opened by any player
|
|
local opened_by_players = {}
|
|
for _,p in pairs(game.players) do
|
|
if p.opened == carriage then
|
|
table.insert(opened_by_players, p)
|
|
end
|
|
end
|
|
|
|
-- Flip orientation if needed
|
|
if flip then
|
|
local foo
|
|
foo,orientation = math.modf(orientation + 0.5)
|
|
end
|
|
|
|
-- Save equipment grid contents
|
|
local grid_equipment = saveRestoreLib.saveGrid(carriage.grid)
|
|
|
|
-- Save item requests left over from a blueprint
|
|
local item_requests = saveRestoreLib.saveItemRequestProxy(carriage)
|
|
|
|
-- Save the burner progress
|
|
local saved_burner = saveRestoreLib.saveBurner(carriage.burner)
|
|
|
|
-- Save the kills stat for artillery wagons
|
|
local kills = nil
|
|
local damage_dealt = nil
|
|
if carriage.type == "artillery-wagon" then
|
|
kills = carriage.kills
|
|
damage_dealt = carriage.damage_dealt
|
|
end
|
|
|
|
-- Save the artillery wagon ammunition inventory
|
|
local ammo_inventory = nil
|
|
local ammo_filters = nil
|
|
if carriage.type == "artillery-wagon" then
|
|
local ammo_inventory_object = carriage.get_inventory(defines.inventory.artillery_wagon_ammo)
|
|
if( ammo_inventory_object and ammo_inventory_object.valid ) then
|
|
ammo_inventory = saveRestoreLib.saveInventoryStacks(ammo_inventory_object)
|
|
ammo_filters = saveRestoreLib.saveFilters(ammo_inventory_object)
|
|
end
|
|
end
|
|
|
|
-- Save the cargo wagon inventory
|
|
local cargo_inventory = nil
|
|
local cargo_filters = nil
|
|
if carriage.type == "cargo-wagon" then
|
|
local cargo_inventory_object = carriage.get_inventory(defines.inventory.cargo_wagon)
|
|
if( cargo_inventory_object and cargo_inventory_object.valid ) then
|
|
cargo_inventory = saveRestoreLib.saveInventoryStacks(cargo_inventory_object)
|
|
cargo_filters = saveRestoreLib.saveFilters(cargo_inventory_object)
|
|
end
|
|
end
|
|
|
|
-- Save the fluid wagon contents
|
|
local fluid_contents = carriage.get_fluid_contents()
|
|
|
|
-- Save the train schedule. If we are replacing a lone MU with a regular carriage, the train schedule will be lost when we delete it.
|
|
local train_schedule = carriage.train.schedule
|
|
local manual_mode = carriage.train.manual_mode
|
|
|
|
-- Save its coupling state. By default, created carriages couple to everything nearby, which we might have to undo
|
|
-- if we're replacing after intentional uncoupling.
|
|
local back_was_connected = carriage.disconnect_rolling_stock(defines.rail_direction.back)
|
|
local front_was_connected = carriage.disconnect_rolling_stock(defines.rail_direction.front)
|
|
|
|
-- Destroy the old Locomotive so we have space to make the new one
|
|
if raiseDestroy == nil then raiseDestroy = true end
|
|
carriage.destroy{raise_destroy=raiseDestroy}
|
|
|
|
------------------------------
|
|
-- Create the new locomotive in the same spot and orientation
|
|
local newCarriage = surface.create_entity{
|
|
name = newName,
|
|
position = position,
|
|
orientation = orientation,
|
|
force = force,
|
|
create_build_effect_smoke = false,
|
|
raise_built = false,
|
|
snap_to_train_stop = false}
|
|
-- make sure it was actually created
|
|
if newCarriage then
|
|
|
|
-- Restore coupling state (if we flipped the wagon, uncouple opposite sides)
|
|
if flip then
|
|
if not front_was_connected then
|
|
newCarriage.disconnect_rolling_stock(defines.rail_direction.back)
|
|
end
|
|
if not back_was_connected then
|
|
newCarriage.disconnect_rolling_stock(defines.rail_direction.front)
|
|
end
|
|
else
|
|
if not front_was_connected then
|
|
newCarriage.disconnect_rolling_stock(defines.rail_direction.front)
|
|
end
|
|
if not back_was_connected then
|
|
newCarriage.disconnect_rolling_stock(defines.rail_direction.back)
|
|
end
|
|
end
|
|
|
|
|
|
-- Restore parameters
|
|
newCarriage.health = health
|
|
if color then newCarriage.color = color end
|
|
if backer_name then newCarriage.backer_name = backer_name end
|
|
if last_user then newCarriage.last_user = last_user end
|
|
if kills then newCarriage.kills = kills end
|
|
if damage_dealt then newCarriage.damage_dealt = damage_dealt end
|
|
newCarriage.minable = minable
|
|
newCarriage.destructible = destructible
|
|
newCarriage.operable = operable
|
|
newCarriage.rotatable = rotatable
|
|
newCarriage.enable_logistics_while_moving = enable_logistics_while_moving
|
|
|
|
|
|
-- Restore the partially-used burner fuel
|
|
if saved_burner then
|
|
local remainders = saveRestoreLib.restoreBurner(newCarriage.burner, saved_burner)
|
|
saveRestoreLib.spillStacks(remainders, surface, position)
|
|
end
|
|
|
|
-- Restore the ammo inventory
|
|
if ammo_inventory or ammo_filters then
|
|
local newAmmoInventory = newCarriage.get_inventory(defines.inventory.artillery_wagon_ammo)
|
|
if newAmmoInventory and newAmmoInventory.valid then
|
|
saveRestoreLib.restoreFilters(newAmmoInventory, ammo_filters)
|
|
local remainders = saveRestoreLib.insertInventoryStacks(newAmmoInventory, ammo_inventory)
|
|
saveRestoreLib.spillStacks(remainders, surface, position)
|
|
end
|
|
end
|
|
|
|
-- Restore the cargo inventory
|
|
if cargo_inventory or cargo_filters then
|
|
local newCargoInventory = newCarriage.get_inventory(defines.inventory.cargo_wagon)
|
|
if newCargoInventory and newCargoInventory.valid then
|
|
saveRestoreLib.restoreFilters(newCargoInventory, cargo_filters)
|
|
local remainders = saveRestoreLib.insertInventoryStacks(newCargoInventory, cargo_inventory)
|
|
saveRestoreLib.spillStacks(remainders, surface, position)
|
|
end
|
|
end
|
|
|
|
-- Restore the fluid wagon contents
|
|
for fluid,amount in pairs(fluid_contents) do
|
|
newCarriage.insert_fluid(fluid,amount)
|
|
end
|
|
|
|
-- Restore the equipment grid
|
|
if grid_equipment and newCarriage.grid and newCarriage.grid.valid then
|
|
local remainders = saveRestoreLib.restoreGrid(newCarriage.grid, grid_equipment)
|
|
saveRestoreLib.spillStacks(remainders, surface, position)
|
|
end
|
|
|
|
-- Restore the player driving
|
|
if player_driving then
|
|
newCarriage.set_driver(player_driving)
|
|
end
|
|
|
|
-- Restore pending deconstruction order
|
|
if deconstruction_request then
|
|
newCarriage.order_deconstruction(deconstruction_request)
|
|
end
|
|
|
|
-- Restore item_request_proxy by creating a new one
|
|
if item_requests then
|
|
surface.create_entity{name="item-request-proxy", position=position, force=force, target=newCarriage, modules=item_requests}
|
|
end
|
|
|
|
-- After all that, fire an event so other scripts can reconnect to it
|
|
if raiseBuilt == nil or raiseBuilt == true then
|
|
script.raise_event(defines.events.script_raised_built, {entity = newCarriage})
|
|
end
|
|
|
|
-- Restore the train schedule and mode
|
|
if train_schedule and train_schedule.records ~= nil then
|
|
local num_stops = 0
|
|
for k,v in pairs(train_schedule.records) do
|
|
num_stops = num_stops + 1
|
|
end
|
|
-- If the schedule is not empty, assign it and restore manual/automatic mode
|
|
if num_stops > 0 then
|
|
newCarriage.train.schedule = train_schedule
|
|
end
|
|
-- If the saved schedule has no stops, do not write to train.schedule. In 0.17.59, this will cause a script error.
|
|
end
|
|
newCarriage.train.manual_mode = manual_mode
|
|
|
|
-- Restore the GUI opened by players
|
|
for _,p in pairs(opened_by_players) do
|
|
p.opened = newCarriage
|
|
end
|
|
|
|
--game.print("Finished replacing. Used direction "..newDirection..", new orientation: " .. newCarriage.orientation)
|
|
return newCarriage
|
|
|
|
else
|
|
-- Could not Create New Wagon
|
|
-- Spill Wagon and Contents on Ground!
|
|
|
|
-- Spill carriage item
|
|
saveRestoreLib.spillStack({name=newName, count=1}, surface, position)
|
|
|
|
-- Spill burner contents
|
|
local r = saveRestoreLib.restoreBurner(nil, saved_burner)
|
|
saveRestoreLib.spillStacks(r, surface, position)
|
|
|
|
-- Spill equipment grid
|
|
local r = saveRestoreLib.restoreGrid(nil, grid_equipment)
|
|
saveRestoreLib.spillStacks(r, surface, position)
|
|
|
|
-- Spill ammo inventory
|
|
saveRestoreLib.spillStacks(ammo_inventory, surface, position)
|
|
|
|
-- Spill cargo inventory
|
|
saveRestoreLib.spillStacks(cargo_inventory, surface, position)
|
|
|
|
return nil
|
|
end
|
|
end
|
|
|
|
return {replaceCarriage = replaceCarriage}
|