Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: Adventurers and deities  (Read 2360 times)

lonewined

  • Escaped Lunatic
    • View Profile
Adventurers and deities
« on: July 28, 2018, 03:11:12 am »

I'm playing Masterwork mod (version 1.30, for Dwarf Fortress version 43.05) and I wish to change my adventurer's deity to another civilization's. I don't want to generate the world again or recreate my adventurer from scratch, as I'm already highly invested in them as they are. My adventurer is an elf from a human civ and has a human deity, and I wish to change it to a specific deity from succubus civ, but there is no temple to that deity in the world (I checked in Legends Viewer) so it's impossible to go about it in a legitimate way by joining her religion. I know it's technically possible to create a fort and retire an adventurer from succubus civ there with that specific deity so I should be able to create a temple to her myself, but 1) it would take a long time I'm not really willing to spend on it and 2) I am not sure a player-created temple would allow my adventurer to join the religion anyway (if anyone made this way work let me know, please, it would be good to know!).

I want the deity-worshipper link to be set up correctly so it's potentially possible for the deity to be able to grant a secret to this character. I've looked around for some time but found no ready tool to do it. I would appreciate it if somebody pointed me in the right direction, or gave a few tips how to go about developing my own script. I'm familiar with programming but not with lua specifically. Do I understand correctly that a character's object of worship information is stored in the same way as marriage information and similar character relationships, so I could base it on a pre-existing marriage script by changing "spouse" to "deity" and probably tweaking a few other minor things? Would the link have to be added for both sides as it would have to be with marriage, or is it the deity-worshipper a one-way relationship link and it would suffice to add it from adventurer's side? All help is highly appreciated!
« Last Edit: October 05, 2018, 03:14:43 pm by lonewined »
Logged

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile
Re: Changing adventurer's deity
« Reply #1 on: July 28, 2018, 03:56:19 am »

it's different from spouses, mostly, it's all stored in hist figure info, you can check a look at that for assistance

lonewined

  • Escaped Lunatic
    • View Profile
Re: Changing adventurer's deity
« Reply #2 on: July 28, 2018, 01:27:03 pm »

it's different from spouses, mostly, it's all stored in hist figure info, you can check a look at that for assistance

The tip about looking into historical figure information was useful in narrowing down what I was looking for. Thank you!

With a bit of snooping through other people's scripts, I managed to figure out a very simple script that appears to be working:
Code: [Select]
-- This script makes a historical figure worship the chosen deity
local deity_name = "Liral"
local worshipper_name = "Istra Twinklingeye"
local deity_id = ""
local worshipper_id = ""
local worshipper = nil


-- Looking for the deity historical figure
for _,fig in ipairs(df.global.world.history.figures) do
 if fig.flags.deity and (tostring (dfhack.TranslateName(fig.name, true))) == deity_name then
  print("Found deity " .. deity_name)
  deity_id = fig.id
  print ("Deity's historical figure id: " .. tostring(deity_id))
  break
 end
end

-- Looking for the worshipper historical figure
for _,fig in ipairs(df.global.world.history.figures) do
 if (tostring (dfhack.TranslateName(fig.name, true))) == worshipper_name then
  print("Found worshipper " .. worshipper_name)
  worshipper_id = fig.id
  worshipper = fig
  print ("Worshipper's historical figure id: " .. tostring(worshipper_id))
  break
 end
end

-- Creating deity link
local deity_link = df.histfig_hf_link_deityst:new()
deity_link.target_hf = deity_id
deity_link.link_strength =  100
worshipper.histfig_links:insert('#', deity_link)
print(worshipper_name .. " is now a worshipper of " .. deity_name)

My adventurer is able to pray to the deity, and with the help of open-legends I can confirm she also has the deity listed in her Legends entry. The next step will be adding the need for my adventurer to pray to the new deity, and removing the link and need related to the old deity.
Logged

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile
Re: Changing adventurer's deity
« Reply #3 on: July 28, 2018, 06:16:56 pm »

For the record, if your adventurer is currently loaded in in adventure mode, you can find their hist figure with df.historical_figure.find(df.global.world.units.active[0].hist_figure_id).

lonewined

  • Escaped Lunatic
    • View Profile
Re: Changing adventurer's deity
« Reply #4 on: July 29, 2018, 02:52:59 am »

For the record, if your adventurer is currently loaded in in adventure mode, you can find their hist figure with df.historical_figure.find(df.global.world.units.active[0].hist_figure_id).

Thank you! Do you perhaps know if there's any sort of collection anywhere that would contain a list of useful code bits like the one you just shared? It would be a really useful thing to have for anybody who's just starting to figure out dfhack scripts.
Logged

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile
Re: Changing adventurer's deity
« Reply #5 on: July 29, 2018, 03:09:31 am »

Any global lists with ordered id fields can be searched that way AFAIK--df.(type_name).find(id) will get you the object with that ID.

There's the ever useful lua api documents

that's about all that i have off the top of my head, though for more obscure stuff i of course always check the xml files that generate them

also, your method of finding historical figure by name is actually the fastest way to do it that i know of, so that's good

lonewined

  • Escaped Lunatic
    • View Profile
Re: Adventurers and deities
« Reply #6 on: October 05, 2018, 03:42:47 pm »

I'm currently trying to write a script that will gift an adventurer a secret-containing artifact slab from a deity, and includes inserting all relevant events into history. I borrowed bits and pieces from various other scripts and figured some stuff out myself, managing to achieve most of what I wanted. Unfortunately, I got stuck on the bit related to creating an event of deity gifting the artifact to an adventurer. For some reason DFHack throws this error:

Code: [Select]
...0 (43.05) 64x\Dwarf Fortress/hack/scripts/DEITY_GIFT.lua:197: attempt to index a nil value (field 'history_event_artifact_givenst')
stack traceback:
        ...0 (43.05) 64x\Dwarf Fortress/hack/scripts/DEITY_GIFT.lua:197: in local 'script_code'
        ...ork V1.30 (43.05) 64x\Dwarf Fortress\hack\lua\dfhack.lua:562: in function 'dfhack.run_script_with_env'

Which relates to following line 197 in my script:
Code: [Select]
local gift = df.history_event_artifact_givenst:new()

The whole script is included below:
Code: [Select]
----------------------------------------------------
-- VARIABLES
----------------------------------------------------

-- Material the slab will be made from

local material = "INORGANIC:MITHRIL"

-- Full name of the secret you want the slab to contain

local secret_type = "the secrets of the light"

-- Full name of the slab as recorded in Legends

local slab_artifact_name = "Blessing of Liral's Divine Fire"

-- Description of the slab

local slab_descritpion = 'The secrets of the light'

-- Full name of the deity that creates the artifact

local deity_name = "Liral"

-- Full name of the person receiving the artifact

local worshipper_name = "Istra Twinklingeye"


----------------------------------------------------
-- FUNCTIONS
----------------------------------------------------


-- Looking for deity's historical figure's id

function getDeityHFID(deity_name)
  local deity_id = ""
  for _,fig in ipairs(df.global.world.history.figures) do
    if fig.flags.deity and (tostring (dfhack.TranslateName(fig.name, true))) == deity_name then
      --print("Found deity " .. deity_name)
      deity_id = fig.id
      --print ("Deity's historical figure id: " .. tostring(deity_id))
      break
    end
  end
  return deity_id
end


-- Looking for worshippers's historical figure's id

function getWorshipperHFID(worshipper_name)
  local worshipper_id = ""
  for _,fig in ipairs(df.global.world.history.figures) do
    if tostring (dfhack.TranslateName(fig.name, true)) == worshipper_name then
      --print("Found worshipper " .. worshipper_name)
      worshipper_id = fig.id
      --print ("Worshipper's historical figure id: " .. tostring(worshipper_id))
      break
    end
  end
  return worshipper_id
end


-- Looking for the secret's ID

function getSecretId(secret_type)
  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_type then
          return i.id
        end
      end
    end
  end
end


----------------------------------------------------
----------------------------------------------------
----------------------------------------------------


-- Checks if the spot to place the slab in-game (mouse cursor's location) is valid

local pos = copyall(df.global.cursor)
if pos.x <0 then
  print ("Invalid slab placement.")
end


-- Checks if the slab's material is valid

local m = dfhack.matinfo.find(material)
if not m then
  print ("Invalid material.")
end


-- Creates the slab as an item in-game

local slab = df.item_slabst:new()
slab.id = df.global.item_next_id
df.global.world.items.all:insert("#",slab)
df.global.item_next_id = df.global.item_next_id+1
slab:setMaterial(m["type"])
slab:setMaterialIndex(m["index"])
slab:categorize(true)
slab.flags.removed = true
slab:setSharpness(0,0)
slab:setQuality(0)
slab.engraving_type = 6
slab.topic = getSecretId(secret_type)
slab.description = tostring(slab_description)

print("Created item")


-- Places the slab on the chosen spot (mouse cursor's location)

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

print("Placed item")


-- Adds the slab as an artifact in Legends

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 = slab
a.name.first_name = slab_artifact_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)

print("Added artifact to Legends")


-- Adds artifact ref

local ref = df.general_ref_is_artifactst:new()
ref.artifact_id = a.id
slab.general_refs:insert("#",ref)
 
df.global.world.items.other.ANY_ARTIFACT:insert("#",slab)

print("Added artifact ref")


-- Adds an event of the slab's creation in Legends
 
local creation = df.history_event_artifact_createdst:new()
creation.year = df.global.cur_year
creation.seconds = df.global.cur_year_tick
creation.id = df.global.hist_event_next_id
creation.artifact_id = a.id
creation.hfid = getDeityHFID(deity_name)

df.global.world.history.events:insert("#",creation)
df.global.hist_event_next_id = df.global.hist_event_next_id+1

print("Added creation event to Legends")


----------------------------------------------------
-- STUFF DOESN'T WORK PAST THIS POINT
----------------------------------------------------

-- Adds an event of deity giving the slab to the adventurer

local gift = df.history_event_artifact_givenst:new()
gift.year = df.global.cur_year
gift.seconds = df.global.cur_year_tick
gift.id = df.global.hist_event_next_id
gift.artifact_id = a.id
gift.giver_hf = getDeityHFID(deity_name)
gift.receiver_hf = getWorshipperHFID(worshipper_name)

df.global.world.history.events:insert("#",gift)
df.global.hist_event_next_id = df.global.hist_event_next_id+1

print("Added gift event to Legends")

The name history_event_artifact_givenst seems to be correct according to https://github.com/DFHack/df-structures. I genuinely have no idea why it's not working, considering the bit with inserting an event of artifact's creation works fine. Any help would be appreciated.
« Last Edit: October 05, 2018, 03:45:21 pm by lonewined »
Logged

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile
Re: Adventurers and deities
« Reply #7 on: October 05, 2018, 09:56:16 pm »

That line doesn't throw up an error for me. I would guess that this is because you are on a very outdated version, 0.43.05 rather than 0.44.12.

lonewined

  • Escaped Lunatic
    • View Profile
Re: Adventurers and deities
« Reply #8 on: October 06, 2018, 06:54:55 am »

I would guess that this is because you are on a very outdated version, 0.43.05 rather than 0.44.12.

This is exactly what the issue was, thank you!
Logged