Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 [2]

Author Topic: prefchange--now with artifake working in fortress or adventurer mode!  (Read 8417 times)

Max™

  • Bay Watcher
  • [CULL:SQUARE]
    • View Profile

Worth noting if you want to add more preferences in a section then you could take say, the steel part (third part) of axeplate (the first section) and copy/paste it along with the pss_counter = pss_counter + 1 above it, so it would look like this:
Code: [Select]
pss_counter = pss_counter + 1
-- likes steel (8)
utils.insert_or_update(unit.status.current_soul.preferences, { new = true, type = 0 , item_type = -1 , creature_id = -1 , color_id = -1 , shape_id = -1 , plant_id = -1 , item_subtype = -1 , mattype = 0 , matindex = dfhack.matinfo.find("STEEL").index , active = true, prefstring_seed = pss_counter }, 'prefstring_seed')
pss_counter = pss_counter + 1
-- likes burning steel (26)
utils.insert_or_update(unit.status.current_soul.preferences, { new = true, type = 0 , item_type = -1 , creature_id = -1 , color_id = -1 , shape_id = -1 , plant_id = -1 , item_subtype = -1 , mattype = 0 , matindex = dfhack.matinfo.find("STEEL_BURNING").index , active = true, prefstring_seed = pss_counter }, 'prefstring_seed')

With the STEEL_BURNING being the appropriate name, you could probably replace the dfhack.matinfo.find("STEEL").index with just 26 if it is the 26th metal (which it should be if it is right after candy, the 25th metal) and it would add that preference accordingly.

I'm still amazed at how clever using the iterated prefstring_seed as a way to add the entries in order without conflicts turned out to be.
« Last Edit: March 16, 2015, 04:57:40 pm by Max™ »
Logged

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile

Oh, I just saved it in the scripts folder as prefchange.lua I would put it on a github page or something but I don't have one

It's completely free, y'know...

Max™

  • Bay Watcher
  • [CULL:SQUARE]
    • View Profile

Yeah, kinda feels like a waste atm to set up for my massive collection of script, I suppose if I get around to some of the other stuff I was thinking about I'll need to make one.
Logged

Max™

  • Bay Watcher
  • [CULL:SQUARE]
    • View Profile

Updated with a show all and clear all option, and shortened the option names.
Logged

Max™

  • Bay Watcher
  • [CULL:SQUARE]
    • View Profile
Re: prefchange--now with artifact faking advfort candy!
« Reply #19 on: May 24, 2015, 09:24:53 pm »

So I worked out how to do something after having the idea for a while, it's still kinda cludgey and I intend to see if I can figure out how to have it assign the names and such but the important thing is it works!


Yes, that is an artifact announcement from an advfort prompt!


I am not sure what happens if you do it with no preferences, but when you have a preference it overwrites the queued job product with the preference product, I had to use a magma forge because I wasn't up for figuring out what the best way to grab the steel rather than the coal was, so bleh.

Then I tried to make it do armor and it kersploded at me so I added another option to set it properly:

(Hauberk is just the flavor name for mail shirts, it's actually [ITEM_ARMOR_MAIL_SHIRT] like normal)

On second thought it is easier to make a second version for adventurer stuff with adventurer relevant addresses.
Code: (artifake.lua) [Select]
local utils = require 'utils'

validArgs = validArgs or utils.invert({
 'help',
 'material',
 'item',
 'name'
})

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

if args.help then
 print(
[[artifake.lua
arguments:
    -help
        print this help message
    -material matstring
        specify the material of the item to be created
        examples:
            INORGANIC:IRON
            CREATURE_MAT:DWARF:BRAIN
            PLANT_MAT:MUSHROOM_HELMET_PLUMP:DRINK
    -item itemstring
        specify the itemdef of the item to be created
        examples:
            WEAPON:ITEM_WEAPON_PICK
    -name namestring
]])
 return
end

args.creator = dfhack.gui.getSelectedUnit()

if not args.item then
 error 'Invalid item.'
end
local itemType = dfhack.items.findType(args.item)
if itemType == -1 then
 error 'Invalid item.'
end
local itemSubtype = dfhack.items.findSubtype(args.item)

args.material = dfhack.matinfo.find(args.material)
if not args.material then
 error 'Invalid material.'
end


local item = dfhack.items.createItem(itemType, itemSubtype, args.material['type'], args.material.index, args.creator)

 local base=df.item.find(df.global.item_next_id-1)
 df.global.world.artifacts.all:new()
 df.global.world.artifacts.all:insert('#',{new=df.artifact_record})
local facts = df.global.world.artifacts.all
 for _,k in ipairs(facts) do
  if k.id==0 then
   local fake=k
   fake.id=df.global.artifact_next_id
   fake.item = {new=base}
fake.item.flags.artifact = true
fake.item.id = base.id
fake.item.general_refs:insert('#',{new =  df.general_ref_is_artifactst})
fake.item.general_refs[0].artifact_id = fake.id
fake.item.spec_heat = base.spec_heat
fake.item.ignite_point = base.ignite_point
fake.item.heatdam_point = base.heatdam_point
fake.item.colddam_point = base.colddam_point
fake.item.boiling_point = base.boiling_point
fake.item.fixed_temp = base.fixed_temp
fake.item.weight = base.weight
fake.item.weight_fraction = base.weight_fraction
fake.item.improvements:insert('#',{new = df.itemimprovement_spikesst,mat_type=25,mat_index=474,quality=0,skill_rating=15})
fake.item.improvements:insert('#',{new = df.itemimprovement_spikesst,mat_type=25,mat_index=493,quality=0,skill_rating=15})
fake.item.improvements:insert('#',{new = df.itemimprovement_art_imagest,mat_type=22,mat_index=474,quality=5,skill_rating=15})
fake.item.improvements:insert('#',{new = df.itemimprovement_art_imagest,mat_type=42,mat_index=480,quality=5,skill_rating=15})
fake.item.improvements:insert('#',{new = df.itemimprovement_art_imagest,mat_type=22,mat_index=497,quality=5,skill_rating=15})
   fake.anon_1 = -1000000
   fake.anon_2 = -1000000
   fake.anon_3 = -1000000
     base.flags.artifact = true
     base.general_refs = fake.item.general_refs
     base.improvements = fake.item.improvements
     fake.item:setQuality(5)
     base:setQuality(5)
     if fake.item == 'WEAPON' then item:setSharpness(1,0) end
     if base == 'WEAPON' then item:setSharpness(1,0) end
     df.global.artifact_next_id=df.global.artifact_next_id+1
 if args.name then do
  fake.name.first_name = args.name
  fake.name.language = 0
  fake.name.has_name = true
         end
      end
   end
end
Leaving the name blank just gives you a masterwork decorated item with artifact type decorations and artifact bonuses, and should you choose to name it later on you can go into df.global.world.artifacts and change it by hand.


OMG THIS IS MADDENING, I have one save that it works great on, I've tried repeatedly with other saves and it doesn't work, instead it just freezes up advfort.

https://github.com/maxthyme/dfstuff/blob/master/artifake.lua
« Last Edit: June 01, 2015, 09:21:48 pm by Max™ »
Logged

Snergler

  • Bay Watcher
  • The world is the same as ever.
    • View Profile
Re: prefchange--now with artifact faking advfort candy!
« Reply #20 on: June 01, 2015, 09:01:46 pm »

nice work! I am having a hiccup though, creatorship is edit:always assigned to the first dwarf in the unit list random AFIAK, even when I use "v" or "k" to view a specific unit. is there a unit or target argument? or is it supposed to work with a unit selected?
i'm talking about artifake.lua :)
« Last Edit: June 01, 2015, 09:15:28 pm by Snergler »
Logged

Max™

  • Bay Watcher
  • [CULL:SQUARE]
    • View Profile
Re: prefchange--now with artifact faking advfort candy!
« Reply #21 on: June 01, 2015, 09:15:56 pm »

Sorry, it's not fully in for fort mode, lemme poke at it and I'll put in a change, atm it's grabbing the adventurer unit.

Code: (artifake.lua) [Select]
local utils = require 'utils'

validArgs = validArgs or utils.invert({
 'help',
 'material',
 'item',
 'name'
})

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

if args.help then
 print(
[[artifake.lua
arguments:
    -help
        print this help message
    -material matstring
        specify the material of the item to be created
        examples:
            INORGANIC:IRON
            CREATURE_MAT:DWARF:BRAIN
            PLANT_MAT:MUSHROOM_HELMET_PLUMP:DRINK
    -item itemstring
        specify the itemdef of the item to be created
        examples:
            WEAPON:ITEM_WEAPON_PICK
    -name namestring
]])
 return
end

if dfhack.gui.getSelectedUnit(true) then
 args.creator = dfhack.gui.getSelectedUnit()
 else args.creator = df.global.world.units.active[0]
end
if not args.item then
 error 'Invalid item.'
end
local itemType = dfhack.items.findType(args.item)
if itemType == -1 then
 error 'Invalid item.'
end
local itemSubtype = dfhack.items.findSubtype(args.item)

args.material = dfhack.matinfo.find(args.material)
if not args.material then
 error 'Invalid material.'
end


local item = dfhack.items.createItem(itemType, itemSubtype, args.material['type'], args.material.index, args.creator)

 local base=df.item.find(df.global.item_next_id-1)
 df.global.world.artifacts.all:new()
 df.global.world.artifacts.all:insert('#',{new=df.artifact_record})
local facts = df.global.world.artifacts.all
 for _,k in ipairs(facts) do
  if k.id==0 then
   local fake=k
   fake.id=df.global.artifact_next_id
   fake.item = {new=base}
fake.item.flags.artifact = true
fake.item.flags.artifact_mood = true
fake.item.id = base.id
fake.item.general_refs:insert('#',{new =  df.general_ref_is_artifactst})
fake.item.general_refs[0].artifact_id = fake.id
fake.item.spec_heat = base.spec_heat
fake.item.ignite_point = base.ignite_point
fake.item.heatdam_point = base.heatdam_point
fake.item.colddam_point = base.colddam_point
fake.item.boiling_point = base.boiling_point
fake.item.fixed_temp = base.fixed_temp
fake.item.weight = base.weight
fake.item.weight_fraction = base.weight_fraction
fake.item.improvements:insert('#',{new = df.itemimprovement_spikesst,mat_type=25,mat_index=474,quality=0,skill_rating=15})
fake.item.improvements:insert('#',{new = df.itemimprovement_spikesst,mat_type=25,mat_index=493,quality=0,skill_rating=15})
fake.item.improvements:insert('#',{new = df.itemimprovement_art_imagest,mat_type=22,mat_index=474,quality=5,skill_rating=15})
fake.item.improvements:insert('#',{new = df.itemimprovement_art_imagest,mat_type=42,mat_index=480,quality=5,skill_rating=15})
fake.item.improvements:insert('#',{new = df.itemimprovement_art_imagest,mat_type=22,mat_index=497,quality=5,skill_rating=15})
   fake.anon_1 = -1000000
   fake.anon_2 = -1000000
   fake.anon_3 = -1000000
     base.flags.artifact = true
     base.flags.artifact_mood = true
     base.general_refs = fake.item.general_refs
     base.improvements = fake.item.improvements
     fake.item:setQuality(5)
     base:setQuality(5)
     if fake.item == 'WEAPON' then item:setSharpness(1,0) end
     if base == 'WEAPON' then item:setSharpness(1,0) end
     df.global.artifact_next_id=df.global.artifact_next_id+1
 if args.name then do
  fake.name.first_name = args.name
  fake.name.language = 0
  fake.name.has_name = true
         end
      end
   end
end

There ya go, that will assign the selected unit as the creator.

https://github.com/maxthyme/dfstuff/blob/master/artifake.lua

Note that I'm still trying to figure out exactly how to get classes and stuff working, I think this is close to working but I'm missing something still:
Code: (nametest.lua) [Select]
name_change = defclass(name_change, choices)
choices = df.new(df.viewscreen_setupadventurest) ; choices.subscreen = 3 ; gui = require 'gui' ; gui.simulateInput(choices, 'A_RANDOM_NAME') ; gui.simulateInput(choices, 'A_CUST_NAME')


function name_change:init()
 local n = dfhack.gui.getCurViewscreen()
end

function name_change:postinit()
  if df.viewscreen_layer_choose_language_namest:is_instance(n) then
      local newn = n.name
    end
  return newn
end

if dfhack.gui.getCurViewscreen().parent == df.viewscreen_itemst then
 local trg = dfhack.gui.getCurViewscreen().parent.item.general_refs[0].artifact_id
 local fact = df.artifact_record.find(trg)
 local oldn = fact.name
elseif dfhack.gui.getCurViewscreen().parent == df.viewscreen_dungeon_monsterstatusst then
 local trg = dfhack.gui.getCurViewscreen().parent.unit
 local oldn = trg.name
return oldn
end

function name_change:onInput(keys)
 if keys.SELECT then
  newn = oldn
 elseif keys.LEAVESCREEN then
  if newn ~= oldn then
     newn = oldn
     self:dismiss()
     choices:dismiss()
    end 
  end
end
The end goal is to have it pull up the name choice screen like when you name a fort or adventurer and then rename the selected unit or artifact with the name from that screen.

Also worth noting that launch.lua no longer slams you into the ground thanks to toady pointing out which flag does the "land on your feet" type jumps:
Code: (launch.lua) [Select]
-- Activate with a cursor on screen and you will go there rapidly, attack something first to send them there.
-- Based on propel.lua by Roses, molested by Rumrusher and I until this happened, sorry.
function launch(unitSource,unitTarget)

local curpos
if df.global.ui_advmode.menu==1 then
curpos=df.global.cursor
else
print ("No cursor located!  You would have slammed into the ground and exploded.") --seriously, kasplut!
return
end


 local count=0
 local l = df.global.world.proj_list
 local lastlist=l
 l=l.next
 while l do
  count=count+1
  if l.next==nil then
   lastlist=l
  end
  l = l.next
 end

resultx = curpos.x - unitSource.pos.x
resulty = curpos.y - unitSource.pos.y
resultz = curpos.z - unitSource.pos.z


 newlist = df.proj_list_link:new()
 lastlist.next=newlist
 newlist.prev=lastlist
 proj = df.proj_unitst:new()
 newlist.item=proj
 proj.link=newlist
 proj.id=df.global.proj_next_id
 df.global.proj_next_id=df.global.proj_next_id+1
 proj.unit=unitSource
 proj.origin_pos.x=unitSource.pos.x
 proj.origin_pos.y=unitSource.pos.y
 proj.origin_pos.z=unitSource.pos.z
 proj.target_pos.x=curpos.x
 proj.target_pos.y=curpos.y
 proj.target_pos.z=curpos.z
 proj.prev_pos.x=unitSource.pos.x
 proj.prev_pos.y=unitSource.pos.y
 proj.prev_pos.z=unitSource.pos.z
 proj.cur_pos.x=unitSource.pos.x
 proj.cur_pos.y=unitSource.pos.y
 proj.cur_pos.z=unitSource.pos.z
 proj.flags.no_impact_destroy=true
 proj.flags.piercing=true
 proj.flags.high_flying=true --this probably doesn't do anything, let me know if you figure out what it is
 proj.flags.parabolic=true
 proj.flags.no_collide=true
 proj.flags.unk9=true
 proj.flags[12]=true
 proj.speed_x=resultx*10000
 proj.speed_y=resulty*10000
 proj.speed_z=resultz*12500 --higher z speed makes it easier to reach a target safely
 unitoccupancy = dfhack.maps.ensureTileBlock(unitSource.pos).occupancy[unitSource.pos.x%16][unitSource.pos.y%16]
 if not unitSource.flags1.on_ground then
  unitoccupancy.unit = false
 else
  unitoccupancy.unit_grounded = false
 end
 unitSource.flags1.projectile=true
 unitSource.flags1.on_ground=false
 end

unitTarget = curpos
if df.global.world.units.active[0].job.hunt_target==nil then
unitSource = df.global.world.units.active[0]
else
unitSource = df.global.world.units.active[0].job.hunt_target --kudos Rumrusher for including this, allowing you to fling others around!
end
 
launch(unitSource,unitTarget)
Though unfortunately that means when you fling people they also land on their feet and I haven't yet tried to make it not do that.
« Last Edit: June 04, 2015, 06:34:19 pm by Max™ »
Logged

Snergler

  • Bay Watcher
  • The world is the same as ever.
    • View Profile
Re: prefchange--now with artifake working in fortress or adventurer mode!
« Reply #22 on: June 01, 2015, 09:39:02 pm »

thanks, it works like a glove!, you rock :D
as a reward, here is an updated version of make.rb
it makes just about every item type, exept items with subtypes, i don't know how to do that :'(
items that have quality levels are base quality, and imported.
Spoiler (click to show/hide)
great for quick fortress mode "testing" :P 
Logged

Max™

  • Bay Watcher
  • [CULL:SQUARE]
    • View Profile
Re: prefchange--now with artifake working in fortress or adventurer mode!
« Reply #23 on: June 01, 2015, 09:45:05 pm »

Nice.

Also figured out how to do the launch stuff properly:
Code: (launch.lua) [Select]
-- Activate with a cursor on screen and you will go there rapidly, attack something first to send them there.
-- Based on propel.lua by Roses, molested by Rumrusher and I until this happened, sorry.
function launch(unitSource,unitTarget)

local curpos
if df.global.ui_advmode.menu==1 then
curpos=df.global.cursor
else
print ("No cursor located!  You would have slammed into the ground and exploded.") --seriously, kasplut!
return
end


 local count=0
 local l = df.global.world.proj_list
 local lastlist=l
 l=l.next
 while l do
  count=count+1
  if l.next==nil then
   lastlist=l
  end
  l = l.next
 end

resultx = curpos.x - unitSource.pos.x
resulty = curpos.y - unitSource.pos.y
resultz = curpos.z - unitSource.pos.z


 newlist = df.proj_list_link:new()
 lastlist.next=newlist
 newlist.prev=lastlist
 proj = df.proj_unitst:new()
 newlist.item=proj
 proj.link=newlist
 proj.id=df.global.proj_next_id
 df.global.proj_next_id=df.global.proj_next_id+1
 proj.unit=unitSource
 proj.origin_pos.x=unitSource.pos.x
 proj.origin_pos.y=unitSource.pos.y
 proj.origin_pos.z=unitSource.pos.z
 proj.target_pos.x=curpos.x
 proj.target_pos.y=curpos.y
 proj.target_pos.z=curpos.z
 proj.prev_pos.x=unitSource.pos.x
 proj.prev_pos.y=unitSource.pos.y
 proj.prev_pos.z=unitSource.pos.z
 proj.cur_pos.x=unitSource.pos.x
 proj.cur_pos.y=unitSource.pos.y
 proj.cur_pos.z=unitSource.pos.z
 proj.flags.no_impact_destroy=true
 proj.flags.piercing=true
 proj.flags.high_flying=true --this probably doesn't do anything, let me know if you figure out what it is
 proj.flags.parabolic=true
 proj.flags.no_collide=true
 proj.flags.unk9=true
 proj.speed_x=resultx*10000
 proj.speed_y=resulty*10000
 proj.speed_z=resultz*12500 --higher z speed makes it easier to reach a target safely
 if df.global.world.units.active[0].job.hunt_target==nil then
  proj.flags[12]=true
 elseif df.global.world.units.active[0].job.hunt_target then
  proj.flags[12]=false
 end
 unitoccupancy = dfhack.maps.ensureTileBlock(unitSource.pos).occupancy[unitSource.pos.x%16][unitSource.pos.y%16]
 if not unitSource.flags1.on_ground then
  unitoccupancy.unit = false
 else
  unitoccupancy.unit_grounded = false
 end
 unitSource.flags1.projectile=true
 unitSource.flags1.on_ground=false
 end

unitTarget = curpos
if df.global.world.units.active[0].job.hunt_target==nil then
unitSource = df.global.world.units.active[0]
else
unitSource = df.global.world.units.active[0].job.hunt_target --kudos Rumrusher for including this, allowing you to fling others around!
end
 
launch(unitSource,unitTarget)

Now it will let YOU land on your feet and THEM slide across the ground.
Logged

Max™

  • Bay Watcher
  • [CULL:SQUARE]
    • View Profile
Re: prefchange--now with artifake working in fortress or adventurer mode!
« Reply #24 on: June 03, 2015, 11:46:03 am »

Whoa, fixed artifake because it was crashing if you didn't select a unit, now it defaults to the adventurer unit unless you select someone else.

Ah ha, thought there was something missing, forgot to flip the artifact_mood flag, that's where the all craftsdwarfship is of the highest quality line comes from!
« Last Edit: June 04, 2015, 06:34:56 pm by Max™ »
Logged

PeridexisErrant

  • Bay Watcher
  • Dai stihó, Hrasht.
    • View Profile
Re: prefchange--now with artifake working in fortress or adventurer mode!
« Reply #25 on: August 31, 2015, 08:43:44 pm »

So I figure this is where to put it, as I said above, I looked around at a couple of scripts to figure out how to turn the all dorfs/all cleared/all same script into this one.  I think I found the "getselectedunit" bit in one from Putnam, and I poked around at a few different things before I got it working in a basic split up form, and then bit by bit was able to assemble it into a single script you can just drop in /hack/scripts:

Code: [Select]
-- Allows setting useful preferences for forcing moods
-- based on pref_adjust by vjek, version 4, 20141016, for DF(hack) 40.08, with the getselectedunit portion from a Putnam script (and the dfhack lua API but he's still a wizard)

By itself: prefchange prints the help, and below that is the error message from trying "prefchange daggerpants" in the thoughts screen (though it does work with anything else that targets a unit: adventurer mode z and l, fort mode k, v, and in even the dwarf manipulator interface thanks to the awesome bit I grabbed from Putnam!)

I went with that order for pairings because that's the order they are in the item_*.txt files, though I skipped over stuff like bows and the weapons that are too large for the average dorf. Should be easy enough to alter them though since I put the smaller parts together first and then took all the axeplate.lua hammershirt.lua etc scripts and assembled them into this one, which works!

Don't have a screenshot but I did force a mood and get a dorf to make a steel helmet after embarking and using prefchange xbh and strangemood -unit -type fey -skill armorsmith -force on them, so, I'd call it a success!

Very cool, nice adaptation/re-use! :)

@vjek, @Max - I've been thinking about getting vjek's scripts into the standard DFHack package for a while now, which would be dead easy with permission and maybe some minor changes.  Are either of you interested in helping, or at least OK with me starting from your work?
Logged
I maintain the DF Starter Pack - over a million downloads and still counting!
 Donations here.

Max™

  • Bay Watcher
  • [CULL:SQUARE]
    • View Profile
Re: prefchange--now with artifake working in fortress or adventurer mode!
« Reply #26 on: August 31, 2015, 09:22:21 pm »

I'm cool with whatever's clever if he is.
Logged

lethosor

  • Bay Watcher
    • View Profile
Re: prefchange--now with artifake working in fortress or adventurer mode!
« Reply #27 on: August 31, 2015, 09:42:48 pm »

I did some work here that makes it fairly easy to pull in scripts from third-party repos (they just have to add a CMakeLists.txt file to specify which scripts should be included). As far as I can tell, your scripts are here, which would be easy to work with, but Vjek's aren't.
Logged
DFHack - Dwarf Manipulator (Lua) - DF Wiki talk

There was a typo in the siegers' campfire code. When the fires went out, so did the game.

Max™

  • Bay Watcher
  • [CULL:SQUARE]
    • View Profile
Re: prefchange--now with artifake working in fortress or adventurer mode!
« Reply #28 on: September 01, 2015, 04:50:31 am »

Yeah I think his are mostly on the wiki as I recall.
Logged
Pages: 1 [2]