117 lines
5.1 KiB
Lua
117 lines
5.1 KiB
Lua
--[[
|
|
"name": "CursorUpgradeCarousel",
|
|
"title": "Cursor Upgrade Carousel",
|
|
"author": "raiguard",
|
|
"description": "Shift+scroll to quickly access an item's upgrades or downgrades. If you do not have the item, the ghost cursor will be used instead (100% not cheaty!). Should be compatible with all mods out of the box, assuming they correctly defined their entities' upgrades. Users can also define their own custom upgrade paths in the mod settings."
|
|
--]]
|
|
local Event = require('__stdlib__/stdlib/event/event')
|
|
|
|
if script.active_mods['CursorUpgradeCarousel'] or script.active_mods['CursorEnhancements'] then
|
|
return
|
|
end
|
|
|
|
-- build upgrade/downgrade registry
|
|
local function build_upgrade_registry()
|
|
local prototypes = game.entity_prototypes
|
|
local data = {}
|
|
-- build default registry
|
|
for name, prototype in pairs(prototypes) do
|
|
if prototype.next_upgrade and prototype.items_to_place_this then
|
|
local upgrade = prototype.next_upgrade.name
|
|
for _, item in ipairs(prototype.items_to_place_this) do
|
|
if not data[item.name] then
|
|
data[item.name] = {}
|
|
end
|
|
data[item.name].upgrade = upgrade
|
|
end
|
|
for _, item in ipairs(prototypes[upgrade].items_to_place_this) do
|
|
if not data[item.name] then
|
|
data[item.name] = {}
|
|
end
|
|
data[item.name].downgrade = name
|
|
end
|
|
end
|
|
end
|
|
-- build custom registry
|
|
for name, upgrade in pairs(load('return ' .. settings.global['picker-carousel-registry'].value)()) do
|
|
-- get objects and validate them, or error if not
|
|
local prototype = prototypes[name]
|
|
if not prototype then
|
|
game.print {'chat-message.invalid-name', name}
|
|
goto continue
|
|
end
|
|
local upgrade_prototype = prototypes[upgrade]
|
|
if not upgrade_prototype then
|
|
game.print {'chat-message.invalid-upgrade-name', upgrade}
|
|
goto continue
|
|
end
|
|
for _, item in ipairs(prototype.items_to_place_this or {}) do
|
|
if not data[item.name] then
|
|
data[item.name] = {}
|
|
end
|
|
data[item.name].upgrade = upgrade
|
|
end
|
|
for _, item in ipairs(upgrade_prototype.items_to_place_this or {}) do
|
|
if not data[item.name] then
|
|
data[item.name] = {}
|
|
end
|
|
data[item.name].downgrade = name
|
|
end
|
|
::continue::
|
|
end
|
|
global.carousel_registry = data
|
|
end
|
|
|
|
Event.on_init(build_upgrade_registry)
|
|
Event.on_configuration_changed(build_upgrade_registry)
|
|
|
|
local matcher = function(event)
|
|
return event and event.setting == 'picker-carousel-registry'
|
|
end
|
|
local runtime_set = defines.events.on_runtime_mod_setting_changed
|
|
Event.on_event(runtime_set, build_upgrade_registry, matcher)
|
|
|
|
local function cycle_carousel(event)
|
|
local player = game.get_player(event.player_index)
|
|
local settings = player.mod_settings
|
|
if settings['picker-use-carousel'].value then
|
|
local stack = player.cursor_stack
|
|
local name
|
|
-- check cursor stack and cursor ghost and set the name accordingly
|
|
if stack and stack.valid_for_read and not stack.is_item_with_label then
|
|
name = stack.name
|
|
elseif player.cursor_ghost then
|
|
name = player.cursor_ghost.name
|
|
else
|
|
return
|
|
end
|
|
|
|
local registry = global.carousel_registry
|
|
-- get upgrade or downgrade depending on event
|
|
local grade = event.input_name:find('forwards') and 'upgrade' or 'downgrade'
|
|
-- if we're in the map editor and the setting is enabled, always give the actual item
|
|
local always_give = settings['picker-carousel-always-give-in-map-editor'].value
|
|
-- if the thing we're holding has an upgrade/downgrade
|
|
if registry[name] and registry[name][grade] and player.clear_cursor() then
|
|
local grade_name = registry[name][grade]
|
|
local inventory = player.get_main_inventory()
|
|
local contents = inventory.get_contents()
|
|
local grade_items = game.entity_prototypes[grade_name].items_to_place_this
|
|
for _, item in ipairs(grade_items) do
|
|
if contents[item.name] then
|
|
-- we actually have this item, so replace the cursor stack from the inventory
|
|
stack.set_stack {name = item.name, count = inventory.remove {name = item.name, count = game.item_prototypes[item.name].stack_size}}
|
|
return
|
|
elseif always_give and player.controller_type == defines.controllers.editor then
|
|
-- replace the cursor stack without taking from the inventory
|
|
stack.set_stack {name = item.name, count = game.item_prototypes[item.name].stack_size}
|
|
return
|
|
end
|
|
end
|
|
-- if we're here, then they don't have any of the items, so put the first one in the ghost cursor
|
|
player.cursor_ghost = grade_items[1].name
|
|
end
|
|
end
|
|
end
|
|
Event.on_event({'picker-carousel-forwards', 'picker-carousel-backwards'}, cycle_carousel)
|