Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: Spawning the secrets of life and death with dfhack  (Read 3629 times)

UristVanHelsing

  • Bay Watcher
    • View Profile
Spawning the secrets of life and death with dfhack
« on: January 07, 2021, 02:03:13 pm »

After visiting 10 necro towers and not finding the secrets of life and death, I decided to spawn them in. The script below is heavily based on the script from http://97.107.128.126/smf/index.php?topic=169149.0

I did some updating so it works with the latest version of DF (.47.04 as of this post). Copy/paste the script into a file called secrets.lua (or whatever) in your hack/scripts directory. Then, just point the cursor where you want the book to spawn and run the command:
Code: [Select]
secrets -material_id INORGANIC:SILVER -booktitle_name "The Necronomicon"
Code: [Select]
--Author: UristVanHelsing
--Heavily based on the amazing work done by Atomic Chicken, Meph, and Burrito25man
--Version: 0.44.XX

local utils = require 'utils'

validArgs = validArgs or utils.invert({
 'material_id',
 'booktitle_name',
 'copy',
 'help'})

local args = utils.processArgs({...}, validArgs)

local artifact = true

if args.help then
 print([[ secrets.lua
 This script is designed to work with a reaction to spawn the secrets of life and death.

 arguments:
 
 -material_id
  Material book will be made of.
 
 -booktitle_name
  Title of the book to be made. String must be contained within ' ' .
 
 -copy
  If this optional argument is included, the script will make the book be treated as a copy

  To use:
 
  Place the cursor where you want the book and run the below command
  secrets -material_id INORGANIC:SILVER -booktitle_name "The Necronomicon"

 ]])
 return
end
 
local material_id = args.material_id
local booktitle_name = args.booktitle_name
local secret_id = 'the secrets of life and death'

if not args.material_id then error 'ERROR: material_id not specified.' end
if not args.booktitle_name then error 'ERROR: booktitle_name not specified.' end
if not args.secret_id then error 'ERROR: secret_id not specified.' end
if args.copy then artifact = false end

function getSecretId(secret_id)
  for _,i in ipairs(df.global.world.raws.interactions) do
    for _,is in ipairs (i.sources) do
      if getmetatable(is) == 'interaction_source_secretst' then
        if is.name == secret_id then
          return i.id
        end
      end
    end
  end
end

local pages = math.random(169,666)
local style = math.random(0,18)

function createWriting(booktitle_name,secret_id)
  local w = df.written_content:new()
  w.id = df.global.written_content_next_id
  w.title = booktitle_name
  w.page_start = 1
  w.page_end = pages --number of pages
  w.styles:insert('#',style) --writing style
  w.style_strength:insert('#',0) --'the writing drives forward relentlessly'
  w.poetic_form = 50 --'the prose is masterful'
 
  local ref = df.general_ref_interactionst:new()
  ref.interaction_id = getSecretId(secret_id)
  ref.source_id = 0
  ref.unk_08 = -1
  ref.unk_0c = -1
  w.refs:insert('#',ref)
  w.ref_aux:insert('#',0)
 
  df.global.written_content_next_id = df.global.written_content_next_id+1
  df.global.world.written_contents.all:insert('#',w)
  return w.id
end

local m = dfhack.matinfo.find(material_id)
if not m then
  error('Invalid material.')
end

local book = df.item_bookst:new()
  book.id = df.global.item_next_id
  df.global.world.items.all:insert('#',book)
  df.global.item_next_id = df.global.item_next_id+1
  book:setMaterial(m['type'])
  book:setMaterialIndex(m['index'])
  book:categorize(true)
  book.flags.removed = true
  book:setSharpness(0,0)
  book:setQuality(0)
  book.title = booktitle_name

local imp = df.itemimprovement_pagesst:new()
  imp.mat_type = m['type']
  imp.mat_index = m['index']
  imp.count = pages --number of pages
  imp.contents:insert('#',createWriting(booktitle_name,secret_id))
  book.improvements:insert('#',imp)

if artifact == true then
  local a = df.artifact_record:new()
  a.id = df.global.artifact_next_id
  df.global.artifact_next_id = df.global.artifact_next_id+1
  a.item = book
  a.name.first_name = booktitle_name
  a.name.has_name = true
  a.flags:assign(df.global.world.artifacts.all[0].flags)
  a.anon_1 = -1000000
  a.anon_2 = -1000000
  a.anon_3 = -1000000
  df.global.world.artifacts.all:insert('#',a)
  local ref = df.general_ref_is_artifactst:new()
  ref.artifact_id = a.id
  book.general_refs:insert('#',ref)
 
  df.global.world.items.other.ANY_ARTIFACT:insert('#',book)
 
  local e = df.history_event_artifact_createdst:new()
  e.year = df.global.cur_year
  e.seconds = df.global.cur_year_tick
  e.id = df.global.hist_event_next_id
  e.artifact_id = a.id
  df.global.world.history.events:insert('#',e)
  df.global.hist_event_next_id = df.global.hist_event_next_id+1
end
local pos = copyall(df.global.cursor)
dfhack.items.moveToGround(book,{x=pos.x,y=pos.y,z=pos.z})

print('A magical book as been created!')
« Last Edit: January 07, 2021, 02:04:50 pm by UristVanHelsing »
Logged
You could always spread it around and paint the floor of your house with the blood of your enemies.
You could very well go for a Christmas themed house, all green and red from blood and vomit. Deck the halls with spilled intestines. Fa la la la la, la la la la!

madpathmoth

  • Bay Watcher
    • View Profile
Re: Spawning the secrets of life and death with dfhack
« Reply #1 on: January 07, 2021, 02:51:45 pm »

Ooh, this is really convenient to have available, thank you for making this.  I'm a little surprised this isn't a common enough desire for something like this to be part of DFhack's default package already.
Logged

Iä! RIAKTOR!

  • Bay Watcher
    • View Profile
Re: Spawning the secrets of life and death with dfhack
« Reply #2 on: January 07, 2021, 05:54:10 pm »

Great! But will it be random secret? Some secrets give you ability to raise lieutenants with only power to cause blisters, when better undeads can have more useful and numerous attacks, also calling upon the night and experimenting (the last one only in worldgen).
Logged

UristVanHelsing

  • Bay Watcher
    • View Profile
Re: Spawning the secrets of life and death with dfhack
« Reply #3 on: January 12, 2021, 07:42:09 am »

Great! But will it be random secret? Some secrets give you ability to raise lieutenants with only power to cause blisters, when better undeads can have more useful and numerous attacks, also calling upon the night and experimenting (the last one only in worldgen).

It's like semi-random? If you run it in different worlds you'll get different secrets, but if you run it multiple times in the same world you'll get the same secret. This is because it just iterates over the secrets vector until it finds one called "the secrets of life and death".
Logged
You could always spread it around and paint the floor of your house with the blood of your enemies.
You could very well go for a Christmas themed house, all green and red from blood and vomit. Deck the halls with spilled intestines. Fa la la la la, la la la la!

Iä! RIAKTOR!

  • Bay Watcher
    • View Profile
Re: Spawning the secrets of life and death with dfhack
« Reply #4 on: January 23, 2021, 02:52:16 pm »

Great! But will it be random secret? Some secrets give you ability to raise lieutenants with only power to cause blisters, when better undeads can have more useful and numerous attacks, also calling upon the night and experimenting (the last one only in worldgen).

It's like semi-random? If you run it in different worlds you'll get different secrets, but if you run it multiple times in the same world you'll get the same secret. This is because it just iterates over the secrets vector until it finds one called "the secrets of life and death".
So, with a little change, it can create my raw defined secret called 'all secrets of life and death'?
Logged

UristVanHelsing

  • Bay Watcher
    • View Profile
Re: Spawning the secrets of life and death with dfhack
« Reply #5 on: January 23, 2021, 02:57:18 pm »

Great! But will it be random secret? Some secrets give you ability to raise lieutenants with only power to cause blisters, when better undeads can have more useful and numerous attacks, also calling upon the night and experimenting (the last one only in worldgen).

It's like semi-random? If you run it in different worlds you'll get different secrets, but if you run it multiple times in the same world you'll get the same secret. This is because it just iterates over the secrets vector until it finds one called "the secrets of life and death".
So, with a little change, it can create my raw defined secret called 'all secrets of life and death'?

Yes, absolutely
Logged
You could always spread it around and paint the floor of your house with the blood of your enemies.
You could very well go for a Christmas themed house, all green and red from blood and vomit. Deck the halls with spilled intestines. Fa la la la la, la la la la!