Last active
December 21, 2022 08:42
-
-
Save ab9rf/4740564 to your computer and use it in GitHub Desktop.
DFHack Ruby script to mark items for purchase in trade screen
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def is_tree_seed? (item) | |
if (!item.instance_of? DFHack::ItemSeedsst) | |
return false | |
end | |
if (item.mat_type < 419 || item.mat_type > 618) | |
return false | |
end | |
mat = df.world.raws.plants.all[item.mat_index] | |
if (! mat.flags[:TREE]) | |
return false | |
end | |
seed_mat_idx = mat.material_defs.type_seed | |
if (seed_mat_idx == -1) | |
return false | |
end | |
seed_mat = mat.material[seed_mat_idx - 419] | |
return !(seed_mat.flags[:EDIBLE_RAW] || seed_mat.flags[:EDIBLE_COOKED]) | |
end | |
def is_scroll? (item) | |
if (!item.instance_of? DFHack::ItemToolst) | |
return false | |
end | |
return item.subtype.tool_use.any?{|u|u==:CONTAIN_WRITING} | |
end | |
def desirable_boulder_mat? (matindex) | |
mat = df.world.raws.inorganics[matindex] | |
(mat.economic_uses.count > 0 || mat.metal_ore.mat_index.count > 0) | |
end | |
def is_metal? (item) | |
return (item.mat_type == 0 && df.world.raws.inorganics[item.mat_index].material.flags[:IS_METAL]) | |
end | |
def is_useful_metal? (item) | |
if (!is_metal? (item)) | |
return false | |
end | |
mat = df.world.raws.inorganics[item.mat_index].material | |
return (mat.flags[:ITEMS_METAL] || | |
mat.flags[:ITEMS_WEAPON] || | |
mat.flags[:ITEMS_WEAPON_RANGED] || | |
mat.flags[:ITEMS_AMMO] || | |
mat.flags[:ITEMS_ARMOR]) | |
end | |
def is_wood? (item) | |
if (item.mat_type < 419 || item.mat_type > 618) | |
return false | |
end | |
mat = df.world.raws.plants.all[item.mat_index].material[item.mat_type-419] | |
mat.flags[:WOOD] | |
end | |
def is_booze? (item) | |
item.instance_of? DFHack::ItemDrinkst | |
end | |
def is_seeds? (item) | |
item.instance_of? DFHack::ItemSeedsst | |
end | |
def is_plantgrowth? (item) | |
item.instance_of? DFHack::ItemPlantGrowthst | |
end | |
def is_milk? (item) | |
if not item.instance_of? DFHack::ItemLiquidMiscst | |
return false | |
end | |
if (item.mat_type < 19 || item.mat_type > 218) | |
return false | |
end | |
mat = df.world.raws.creatures.all[item.mat_index].material[item.mat_type-19] | |
mat.reaction_class.any? {|i|i == "MILK"} | |
end | |
def is_flour? (item) | |
if not item.instance_of? DFHack::ItemPowderMiscst | |
return false | |
end | |
if (item.mat_type < 419 || item.mat_type > 618) | |
return false | |
end | |
mat = df.world.raws.plants.all[item.mat_index].material[item.mat_type-419] | |
mat.flags[:POWDER_MISC_PLANT] | |
end | |
def is_salve? (item) | |
if not item.instance_of? DFHack::ItemLiquidMiscst | |
return false | |
end | |
if (item.mat_type < 419 || item.mat_type > 618) | |
return false | |
end | |
mat = df.world.raws.plants.all[item.mat_index].material[item.mat_type-419] | |
mat.flags[:LIQUID_MISC_PLANT] | |
end | |
def is_syrup? (item) | |
if not item.instance_of? DFHack::ItemLiquidMiscst | |
return false | |
end | |
if (item.mat_type < 419 || item.mat_type > 618) | |
return false | |
end | |
mat = df.world.raws.plants.all[item.mat_index].material[item.mat_type-419] | |
mat.flags[:LIQUID_MISC_PLANT] && | |
(mat.flags[:EDIBLE_COOKED] || mat.flags[:EDIBLE_RAW]) | |
end | |
def is_lye? (item) | |
if not item.instance_of? DFHack::ItemLiquidMiscst | |
return false | |
end | |
item.mat_type == 11 | |
end | |
def is_sand? (item) | |
if not item.instance_of? DFHack::ItemPowderMiscst | |
return false | |
end | |
if (item.mat_type != 0) | |
return false | |
end | |
mat = df.world.raws.inorganics[item.mat_index] | |
mat.flags[:SOIL_SAND] | |
end | |
def is_plaster? (item) | |
if not item.instance_of? DFHack::ItemPowderMiscst | |
return false | |
end | |
if (item.mat_type != 0) | |
return false | |
end | |
mat = df.world.raws.inorganics[item.mat_index] | |
mat.material.hardens_with_water.mat_type != -1 | |
end | |
def cage_nonempty? (item) | |
item.general_refs.any? {|r| r.instance_of? DFHack::GeneralRefContainsUnitst} | |
end | |
def container_empty? (item) | |
not (item.general_refs.any? {|r| r.instance_of? DFHack::GeneralRefContainsItemst}) | |
end | |
def contents (item) | |
result = item.general_refs.find {|r| (r.instance_of? DFHack::GeneralRefContainsItemst)} | |
result = result && result.item_tg | |
end | |
def contents_list (item) | |
result = item.general_refs.find_all {|r| (r.instance_of? DFHack::GeneralRefContainsItemst)} | |
result = result && result.map {|r|r.item_tg} | |
end | |
def trader_desirable? (item) | |
if (((item.instance_of? DFHack::ItemFlaskst) && | |
(contents_list(item).any?{|c|is_salve?(c)})) || | |
(item.instance_of? DFHack::ItemFoodst)) | |
return false | |
end | |
(is_booze?(item)) or | |
(is_milk?(item)) or | |
(is_syrup?(item)) or | |
(is_lye?(item)) or | |
(is_flour?(item)) or | |
(is_sand?(item)) or | |
(is_seeds?(item) && !is_tree_seed?(item)) or | |
(is_scroll?(item)) or | |
(is_plaster?(item)) or | |
(item.instance_of? DFHack::ItemCoinst) or | |
(item.instance_of? DFHack::ItemInstrumentst) or | |
(item.instance_of? DFHack::ItemCheesest) or | |
(item.instance_of? DFHack::ItemMeatst) or | |
(item.instance_of? DFHack::ItemEggst) or | |
(item.instance_of? DFHack::ItemFishst) or | |
(item.instance_of? DFHack::ItemBarst) or | |
(item.instance_of? DFHack::ItemSmallgemst) or | |
(item.instance_of? DFHack::ItemRoughst) or | |
(item.instance_of? DFHack::ItemBookst) or | |
((item.instance_of? DFHack::ItemBoulderst) && desirable_boulder_mat?(item.mat_index)) or | |
(item.instance_of? DFHack::ItemWoodst) or | |
(((((item.instance_of? DFHack::ItemBinst) || | |
(item.instance_of? DFHack::ItemBoxst) || | |
(item.instance_of? DFHack::ItemBarrelst) || | |
(item.instance_of? DFHack::ItemBackpackst) || | |
(item.instance_of? DFHack::ItemCabinetst)) && container_empty?(item)) || | |
(item.instance_of? DFHack::ItemArmorstandst) || | |
(item.instance_of? DFHack::ItemWeaponrackst) || | |
(item.instance_of? DFHack::ItemGratest) || | |
(item.instance_of? DFHack::ItemFlaskst) || | |
(item.instance_of? DFHack::ItemBucketst) || | |
(item.instance_of? DFHack::ItemBedst) || | |
(item.instance_of? DFHack::ItemDoorst) || | |
(item.instance_of? DFHack::ItemChairst) || | |
(item.instance_of? DFHack::ItemTablest) || | |
(item.instance_of? DFHack::ItemSlabst) || | |
(item.instance_of? DFHack::ItemCoffinst) || | |
(item.instance_of? DFHack::ItemStatuest) || | |
(item.instance_of? DFHack::ItemTrappartsst) || | |
(item.instance_of? DFHack::ItemQuiverst) || | |
(item.instance_of? DFHack::ItemWeaponst) || | |
(item.instance_of? DFHack::ItemArmorst) || | |
(item.instance_of? DFHack::ItemShoesst) || | |
(item.instance_of? DFHack::ItemShieldst) || | |
(item.instance_of? DFHack::ItemHelmst) || | |
(item.instance_of? DFHack::ItemGlovesst) || | |
(item.instance_of? DFHack::ItemAmmost) || | |
(item.instance_of? DFHack::ItemAnvilst) || | |
(item.instance_of? DFHack::ItemPantsst) || | |
(item.instance_of? DFHack::ItemTrapcompst) || | |
(item.instance_of? DFHack::ItemChainst) || | |
(item.instance_of? DFHack::ItemSplintst) || | |
(item.instance_of? DFHack::ItemToolst) || | |
(item.instance_of? DFHack::ItemCrutchst) || | |
(item.instance_of? DFHack::ItemSheetst) || | |
(item.instance_of? DFHack::ItemGobletst)) && | |
((is_useful_metal?(item)) || | |
((item.wear == 0) && (item.quality == :Masterful || item.quality == :Artifact)))) or | |
(((item.instance_of? DFHack::ItemToyst) || | |
(item.instance_of? DFHack::ItemBraceletst) || | |
(item.instance_of? DFHack::ItemCrownst) || | |
(item.instance_of? DFHack::ItemFigurinest) || | |
(item.instance_of? DFHack::ItemAmuletst) || | |
(item.instance_of? DFHack::ItemScepterst) || | |
(item.instance_of? DFHack::ItemRingst) || | |
(item.instance_of? DFHack::ItemEarringst) || | |
(item.instance_of? DFHack::ItemGemst)) && | |
(is_useful_metal?(item) && | |
!(item.quality == :Masterful || item.quality == :Artifact))) or | |
((item.instance_of? DFHack::ItemCagest)) or | |
(((item.instance_of? DFHack::ItemBarrelst) || | |
(item.instance_of? DFHack::ItemToolst) || | |
(item.instance_of? DFHack::ItemBoxst)) && | |
(contents_list(item).any?{|c|trader_desirable?(c)})) or | |
((item.instance_of? DFHack::ItemClothst)) or | |
((item.instance_of? DFHack::ItemSkinTannedst)) or | |
((item.instance_of? DFHack::ItemPlantst)) or | |
((item.instance_of? DFHack::ItemPlantGrowthst)) or | |
((item.instance_of? DFHack::ItemThreadst)) or | |
false | |
end | |
def is_wood_based? (typ, idx) | |
if (typ == 11) # lye | |
return true | |
end | |
if (typ == 4 || typ == 5) # clear & crystal glass | |
return true | |
end | |
mat = DFHack::decode_mat(typ, idx) | |
return mat && mat.material && (mat.material.flags[:WOOD] || mat.material.flags[:SOAP]) | |
end | |
def contains_wood?(item) | |
mat_type = item.getMaterial() | |
mat_index = item.getMaterialIndex() | |
if is_wood_based?(mat_type, mat_index) | |
# puts "wood: #{item.inspect}" | |
return true | |
end | |
if ((item.kind_of? DFHack::ItemConstructed) && | |
item.improvements.any? {|imp| | |
res=is_wood_based?(imp.mat_type, imp.mat_index) | |
res | |
}) | |
# puts "wood in improvements: #{item.inspect}" | |
return true | |
end | |
if (item.flags.container && contents_list(item).any? {|c|contains_wood?(c)}) | |
# puts "wood in contents: #{item.inspect}" | |
return true | |
end | |
false | |
end | |
def broker_desirable? (item, nowood=false) | |
if item.flags.artifact then | |
return false | |
end | |
if df.world.mandates.any? {|m| | |
m.mode == 0 && m.item_type == item.getType() && | |
(m.item_subtype == -1 || m.item_subtype == item.getSubtype()) && | |
(m.mat_type == -1 || m.mat_type == item.getMaterial()) && | |
(m.mat_index == -1 || m.mat_type == item.getMaterialIndex()) } | |
return false | |
end | |
if ((item.instance_of? DFHack::ItemBoulderst) || | |
(item.instance_of? DFHack::ItemMeatst) || | |
(item.instance_of? DFHack::ItemCheesest) || | |
(item.instance_of? DFHack::ItemFishst) || | |
(item.instance_of? DFHack::ItemFishRawst) || | |
(item.instance_of? DFHack::ItemEggst) || | |
(item.instance_of? DFHack::ItemGlobst) || | |
(item.instance_of? DFHack::ItemBinst) || | |
(item.instance_of? DFHack::ItemCagest) || | |
(item.instance_of? DFHack::ItemBlocksst) || | |
(item.instance_of? DFHack::ItemCorpsepiecest)) || | |
(item.instance_of? DFHack::ItemTrappartsst) || | |
(item.instance_of? DFHack::ItemDoorst) || | |
(item.instance_of? DFHack::ItemCabinetst) || | |
(item.instance_of? DFHack::ItemBoxst) || | |
(item.instance_of? DFHack::ItemCoffinst) || | |
(item.instance_of? DFHack::ItemBedst) | |
return false | |
end | |
if (((item.instance_of? DFHack::ItemBarrelst) || | |
# (item.instance_of? DFHack::ItemBucketst) || | |
(item.instance_of? DFHack::ItemToolst) || | |
(item.instance_of? DFHack::ItemBoxst)) && | |
contents_list(item).empty?) | |
return false | |
end | |
if (nowood && contains_wood?(item)) | |
return false | |
end | |
if (nowood && item.weight >= 50 ) | |
return false | |
end | |
des = ! trader_desirable?(item) | |
if (des) | |
return true | |
end | |
return false | |
end | |
def find_broker () | |
broker = df.unit_citizens.find{|u| | |
ep = df.unit_entitypositions(u) | |
ep.find{|r|r.responsibilities[:TRADE]} | |
} | |
end | |
nowood = false | |
case $script_args[0] | |
when 'test' | |
item = DFHack::item_find | |
if (item) | |
td = trader_desirable?(item) | |
bd = broker_desirable?(item) | |
bdc = (! (contents_list(item).empty?) && | |
(contents_list(item).any? {|c| broker_desirable?(c)})) | |
puts "TD: #{td} BD: #{bd} BDC: #{bdc}" | |
end | |
runmode = :Nothing | |
when 'clear' | |
runmode = :Clear | |
when 'clearpend' | |
runmode = :Clearpend | |
when 'cpnb' | |
runmode = :CPNB | |
when 'clearbroker' | |
runmode = :ClearBroker | |
when 'cleartrader' | |
runmode = :ClearTrader | |
when 'nowood' | |
runmode = :Set | |
nowood = true | |
when 'wt' | |
runmode = :WT | |
when 'unmark' | |
runmode = :Unmark | |
arg = $script_args[1] | |
else | |
runmode = :Set | |
end | |
if runmode != :Nothing then | |
broker = find_broker | |
civ = broker.civ_tg | |
vs = df.gview.view.child.child | |
if (vs.instance_of? DFHack::ViewscreenLayerAssigntradest) | |
vs.info.each {|i| | |
case runmode | |
when :Clear | |
des = false | |
when :Set | |
item = i.item | |
td = trader_desirable?(item) | |
bd = ((broker_desirable?(item,nowood))) | |
bd = bd || (!(item.instance_of? DFHack::ItemBarrelst) && | |
contents_list(item).any? {|c| broker_desirable?(c,nowood)}) | |
des = !td && (bd) | |
when :Clearpend | |
des = (i.status == :Trading) || | |
((i.status == :Pending || i.status == :AddPending) && i.distance == 0) | |
when :CPNB | |
des = (i.status == :Trading) || | |
((i.status == :Pending || i.status == :AddPending) && ((i.distance == 0) || (i.item.instance_of? DFHack::ItemBinst))) | |
else | |
des = (i.status == :AddPending || i.status == :Pending || i.status == :Trading) | |
end | |
stat = i.status | |
if (des) | |
if i.status == :None | |
i.status = :AddPending | |
elsif i.status == 255 | |
i.status = :Pending | |
elsif i.status == 254 | |
i.status = :Trading | |
end | |
else | |
if i.status == :AddPending | |
i.status = :None | |
elsif i.status == :Pending | |
i.status = :RemovePending | |
elsif i.status == :Trading | |
i.status = :RemoveTrading | |
end | |
end | |
} | |
elsif (vs.instance_of? DFHack::ViewscreenTradelistst) | |
vs = vs.child | |
wood_ethic = vs.entity.entity_raw.ethic[:KILL_PLANT] | |
nowood = nowood || | |
wood_ethic == :MISGUIDED || | |
wood_ethic == :SHUN || | |
wood_ethic == :APPALLING || | |
wood_ethic == :PUNISH_REPRIMAND || | |
wood_ethic == :PUNISH_SERIOUS || | |
wood_ethic == :PUNISH_EXILE || | |
wood_ethic == :PUNISH_CAPITAL || | |
wood_ethic == :UNTHINKABLE | |
case runmode | |
when :Clear | |
(0...vs.trader_items.count).each {|i| | |
item = vs.trader_items[i] | |
vs.trader_selected[i] = false | |
} | |
(0...vs.broker_items.count).each {|i| | |
item = vs.broker_items[i] | |
vs.broker_selected[i] = false | |
} | |
when :ClearBroker | |
(0...vs.broker_items.count).each {|i| | |
item = vs.broker_items[i] | |
vs.broker_selected[i] = false | |
} | |
when :ClearTrader | |
(0...vs.trader_items.count).each {|i| | |
item = vs.trader_items[i] | |
vs.trader_selected[i] = false | |
} | |
when :Set | |
(0...vs.trader_items.count).each {|i| | |
item = vs.trader_items[i] | |
vs.trader_selected[i] = trader_desirable? (item) | |
} | |
(0...vs.broker_items.count).each {|i| | |
item = vs.broker_items[i] | |
vs.broker_selected[i] = broker_desirable?(item, nowood) | |
} | |
when :Unmark | |
(0...vs.trader_items.count).each {|i| | |
item = vs.trader_items[i] | |
if (vs.trader_selected[i]) | |
str = DFHack::StlString.cpp_new | |
vs.trader_items[i].getItemDescription(str, 0) | |
if (str.str.include?(arg)) | |
vs.trader_selected[i] = false | |
end | |
end | |
} | |
(0...vs.broker_items.count).each {|i| | |
item = vs.broker_items[i] | |
if (vs.broker_selected[i]) | |
str = DFHack::StlString.cpp_new | |
vs.broker_items[i].getItemDescription(str, 0) | |
if (str.str.include?(arg)) | |
vs.broker_selected[i] = false | |
end | |
end | |
} | |
when :WT | |
while (vs.broker_cursor < vs.broker_items.count) | |
vs.broker_cursor = vs.broker_cursor + 1 | |
item = vs.broker_items[vs.broker_cursor] | |
break if (contains_wood?(item)) | |
end | |
end | |
else | |
puts "Invalid invocation context!" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment