Bay 12 Games Forum

Dwarf Fortress => DF Modding => Utilities and 3rd Party Applications => Topic started by: burrito25man on January 15, 2018, 01:49:30 am

Title: LUA advice for script that spawns necomancer codices for fortress mode
Post by: burrito25man on January 15, 2018, 01:49:30 am
Good morning all

For the past week I've been troubleshooting a script that I made based on a script posted somewhere here by Atomic Chicken, that allows for the creation of necromancer codices. The purpose of my script is to spawn a magic codex when used with modtools/reaction-trigger. Based on testing, it is able to spawn the books, but I can't seem to figure out how to make the scipt place the book under the worker's feet.

Here's the script in the raw, please excuse all the comments. As is it will spawn a codex and it will show on the stocks screen, but it's location is a mystery.
Code: [Select]
--Author: Burrito25man
--Based off the amazing work done by Atomic Chicken
--Version: 0.44.04

local utils = require 'utils'

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

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

local artifact = true

if args.help then
 print([[ Spawn spellbook.lua
 This script is designed to work with a reaction to spawn a spellbook.

 arguments:
 
 -material_id
Material book will be made of.

 -booktitle_name
Title of the book to be made. String must be contained within ' ' .

 -secret_id
Secret conveyed by the book (must use the IS_NAME of the secret). String must be contained within ' ' .

 -copy
If this optional argument is included, the script will make the book be treated as a copy

 -location
Location which the book will spawn.

  To use:
 
 Create a file called "onLoad.init" in Dwarf Fortress/raw if one does not already exist.
 Enter the following:
  modtools/reaction-trigger -reactionName YOUR_REACTION -command [ Spawn-spellbook -material_id MATERIAL -booktitle_name "BOOK TITLE" -secret_id "SECRET ID" -location \\LOCATION -copy]
 
  such as:
 
  modtools/reaction-trigger -reactionName SPAWN_NECROBOOK -command [ Spawn-spellbook -material_id INORGANIC:SILVER -booktitle_name "The Necronomicon" -secret_id "the secrets of life and death" -location \\LOCATION -copy]

 ]])
 return
end

print('args.location')
print(' ')
print(args.location)

local material_id = args.material_id
local booktitle_name = args.booktitle_name
local secret_id = args.secret_id


--print(args.location)
--position = df.unit.find(tonumber(args.location))
--print('Position of unit from df.unit.find(tonumber(args.location))')
--print(position)
--local position = {dfhack.units.getPosition(args.location)}


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

print(' ')
print('Material')
print(args.material_id)
print(' ')
print('Title')
print(args.booktitle_name)
print(' ')
print('secret id')
print(args.secret_id)
print(' ')

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

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 = 42--number of pages
  w.styles:insert('#',7)--(forceful)
  w.style_strength:insert('#',0)--'the writing drives forward relentlessly'
  w.anon_3 = 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 pos = position.pos
print('pos')
print(location.pos.x)
print(pos.x)

local pos = copyall(df.global.cursor)
if pos.x <0 then
  error('Please place the cursor wherever you want to spawn the slab.')
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 = 666 --number of pages
imp.contents:insert('#',createWriting(booktitle_name,secret_id))
book.improvements:insert('#',imp)
book.flags2.has_written_content = true

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

dfhack.items.moveToGround(book,[args.location])

I'm open to any ideas. I'm still teaching myself LUA through scripts by other people, so please excuse if there's an obvious solution  :-[
Title: Re: LUA advice for script that spawns necomancer codices for fortress mode
Post by: Meph on January 16, 2018, 12:22:52 pm
Try \\WORKER_ID instead of LOCATION. And try both with three \\\.
Title: Re: LUA advice for script that spawns necomancer codices for fortress mode
Post by: burrito25man on January 19, 2018, 03:07:26 pm
SUCCESS!!!!!!

(https://i.imgur.com/B5Twecw.gif)

1000 thanks Meph!!! Here's the code, for anyone that wants it. I'll change up the posting to make it more official to download later  :D :D :D

Code: [Select]
--Author: Burrito25man
--Based off the amazing work done by Atomic Chicken and Meph for guidance
--Version: 0.44.XX

local utils = require 'utils'

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

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

local artifact = true

if args.help then
 print([[ Spawn spellbook.lua
 This script is designed to work with a reaction to spawn a spellbook.

 arguments:
 
 -material_id
Material book will be made of.

 -booktitle_name
Title of the book to be made. String must be contained within ' ' .

 -secret_id
Secret conveyed by the book (must use the IS_NAME of the secret). String must be contained within ' ' .

 -copy
If this optional argument is included, the script will make the book be treated as a copy

 -location
Location which the book will spawn.

  To use:
 
 Create a file called "onLoad.init" in Dwarf Fortress/raw if one does not already exist.
 Enter the following:
  modtools/reaction-trigger -reactionName YOUR_REACTION -command [ Spawn-spellbook -material_id MATERIAL -booktitle_name "BOOK TITLE" -secret_id "SECRET ID" -location \\WORKER_ID -copy]
 
  such as:
 
  modtools/reaction-trigger -reactionName SPAWN_NECROBOOK -command [ Spawn-spellbook -material_id INORGANIC:SILVER -booktitle_name "The Necronomicon" -secret_id "the secrets of life and death" -location \\WORKER_ID -copy ]

 ]])
 return
end

local material_id = args.material_id
local booktitle_name = args.booktitle_name
local secret_id = args.secret_id
local worker = df.unit.find(tonumber(args.location))

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.anon_3 = 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)
book.flags2.has_written_content = true

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

dfhack.items.moveToGround(book,{x=worker.pos.x,y=worker.pos.y,z=worker.pos.z})

print('A magical book as been created!')



Title: Re: LUA advice for script that spawns necomancer codices for fortress mode
Post by: Atomic Chicken on February 02, 2018, 08:37:47 am
Oh hey, kudos for continuing work on this script! I'd actually written an updated version to add this sort of functionality shortly after posting the requested version, but I never got around to publishing it (as is unfortunately the case with most of the stuff I've written).

I'm still teaching myself LUA through scripts by other people, so please excuse if there's an obvious solution  :-[
Pretty much the same way most of us learnt this stuff! You seem to be doing fine.