179 lines
4.8 KiB
Lua
179 lines
4.8 KiB
Lua
|
-- Injects new reaction, item and building defs into the world.
|
||
|
|
||
|
-- The savegame contains a list of the relevant definition tokens in
|
||
|
-- the right order, but all details are read from raws every time.
|
||
|
-- This allows just adding stub definitions, and simply saving and
|
||
|
-- reloading the game.
|
||
|
|
||
|
local utils = require 'utils'
|
||
|
|
||
|
local raws = df.global.world.raws
|
||
|
|
||
|
print[[
|
||
|
WARNING: THIS SCRIPT CAN PERMANENLY DAMAGE YOUR SAVE.
|
||
|
|
||
|
This script attempts to inject new raw objects into your
|
||
|
world. If the injected references do not match the actual
|
||
|
edited raws, your save will refuse to load, or load but crash.
|
||
|
]]
|
||
|
|
||
|
if not utils.prompt_yes_no('Did you make a backup?') then
|
||
|
qerror('Not backed up.')
|
||
|
end
|
||
|
|
||
|
df.global.pause_state = true
|
||
|
|
||
|
local changed = false
|
||
|
|
||
|
function inject_reaction(name)
|
||
|
for _,v in ipairs(raws.reactions) do
|
||
|
if v.code == name then
|
||
|
print('Reaction '..name..' already exists.')
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
|
||
|
print('Injecting reaction '..name)
|
||
|
changed = true
|
||
|
|
||
|
raws.reactions:insert('#', {
|
||
|
new = true,
|
||
|
code = name,
|
||
|
name = 'Dummy reaction '..name,
|
||
|
index = #raws.reactions,
|
||
|
})
|
||
|
end
|
||
|
|
||
|
local building_types = {
|
||
|
workshop = { df.building_def_workshopst, raws.buildings.workshops },
|
||
|
furnace = { df.building_def_furnacest, raws.buildings.furnaces },
|
||
|
}
|
||
|
|
||
|
function inject_building(btype, name)
|
||
|
for _,v in ipairs(raws.buildings.all) do
|
||
|
if v.code == name then
|
||
|
print('Building '..name..' already exists.')
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
|
||
|
print('Injecting building '..name)
|
||
|
changed = true
|
||
|
|
||
|
local typeinfo = building_types[btype]
|
||
|
|
||
|
local id = raws.buildings.next_id
|
||
|
raws.buildings.next_id = id+1
|
||
|
|
||
|
raws.buildings.all:insert('#', {
|
||
|
new = typeinfo[1],
|
||
|
code = name,
|
||
|
name = 'Dummy '..btype..' '..name,
|
||
|
id = id,
|
||
|
})
|
||
|
|
||
|
typeinfo[2]:insert('#', raws.buildings.all[#raws.buildings.all-1])
|
||
|
end
|
||
|
|
||
|
local itemdefs = raws.itemdefs
|
||
|
local item_types = {
|
||
|
weapon = { df.itemdef_weaponst, itemdefs.weapons, 'weapon_type' },
|
||
|
trainweapon = { df.itemdef_weaponst, itemdefs.weapons, 'training_weapon_type' },
|
||
|
pick = { df.itemdef_weaponst, itemdefs.weapons, 'digger_type' },
|
||
|
trapcomp = { df.itemdef_trapcompst, itemdefs.trapcomps, 'trapcomp_type' },
|
||
|
toy = { df.itemdef_toyst, itemdefs.toys, 'toy_type' },
|
||
|
tool = { df.itemdef_toolst, itemdefs.tools, 'tool_type' },
|
||
|
instrument = { df.itemdef_instrumentst, itemdefs.instruments, 'instrument_type' },
|
||
|
armor = { df.itemdef_armorst, itemdefs.armor, 'armor_type' },
|
||
|
ammo = { df.itemdef_ammost, itemdefs.ammo, 'ammo_type' },
|
||
|
siegeammo = { df.itemdef_siegeammost, itemdefs.siege_ammo, 'siegeammo_type' },
|
||
|
gloves = { df.itemdef_glovest, itemdefs.gloves, 'gloves_type' },
|
||
|
shoes = { df.itemdef_shoest, itemdefs.shoes, 'shoes_type' },
|
||
|
shield = { df.itemdef_shieldst, itemdefs.shields, 'shield_type' },
|
||
|
helm = { df.itemdef_helmst, itemdefs.helms, 'helm_type' },
|
||
|
pants = { df.itemdef_pantsst, itemdefs.pants, 'pants_type' },
|
||
|
food = { df.itemdef_foodst, itemdefs.food },
|
||
|
}
|
||
|
|
||
|
function add_to_civ(entity, bvec, id)
|
||
|
for _,v in ipairs(entity.resources[bvec]) do
|
||
|
if v == id then
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
|
||
|
entity.resources[bvec]:insert('#', id)
|
||
|
end
|
||
|
|
||
|
function add_to_dwarf_civs(btype, id)
|
||
|
local typeinfo = item_types[btype]
|
||
|
if not typeinfo[3] then
|
||
|
print('Not adding to civs.')
|
||
|
end
|
||
|
|
||
|
for _,entity in ipairs(df.global.world.entities.all) do
|
||
|
if entity.race == df.global.ui.race_id then
|
||
|
add_to_civ(entity, typeinfo[3], id)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function inject_item(btype, name)
|
||
|
for _,v in ipairs(itemdefs.all) do
|
||
|
if v.id == name then
|
||
|
print('Itemdef '..name..' already exists.')
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
|
||
|
print('Injecting item '..name)
|
||
|
changed = true
|
||
|
|
||
|
local typeinfo = item_types[btype]
|
||
|
local vec = typeinfo[2]
|
||
|
local id = #vec
|
||
|
|
||
|
vec:insert('#', {
|
||
|
new = typeinfo[1],
|
||
|
id = name,
|
||
|
subtype = id,
|
||
|
name = name,
|
||
|
name_plural = name,
|
||
|
})
|
||
|
|
||
|
itemdefs.all:insert('#', vec[id])
|
||
|
|
||
|
add_to_dwarf_civs(btype, id)
|
||
|
end
|
||
|
|
||
|
local args = {...}
|
||
|
local mode = nil
|
||
|
local ops = {}
|
||
|
|
||
|
for _,kv in ipairs(args) do
|
||
|
if mode and string.match(kv, '^[%u_]+$') then
|
||
|
table.insert(ops, curry(mode, kv))
|
||
|
elseif kv == 'reaction' then
|
||
|
mode = inject_reaction
|
||
|
elseif building_types[kv] then
|
||
|
mode = curry(inject_building, kv)
|
||
|
elseif item_types[kv] then
|
||
|
mode = curry(inject_item, kv)
|
||
|
else
|
||
|
qerror('Invalid option: '..kv)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if #ops > 0 then
|
||
|
print('')
|
||
|
for _,v in ipairs(ops) do
|
||
|
v()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if changed then
|
||
|
print('\nNow without unpausing save and reload the game to re-read raws.')
|
||
|
else
|
||
|
print('\nNo changes made.')
|
||
|
end
|