From ad09bc98d1e4f287a8033f14ca8c265df791391e Mon Sep 17 00:00:00 2001 From: PeridexisErrant Date: Wed, 1 Apr 2015 10:23:09 +1100 Subject: [PATCH 1/2] Add script, content, and documentation See readme diff for more information. A follow-up pull will eventually come to complete the description coverage. --- NEWS | 1 + Readme.rst | 11 + dfhack.init-example | 3 + scripts/item-descriptions.lua | 88 ++++++++ scripts/view-item-info.lua | 380 ++++++++++++++++++++++++++++++++++ 5 files changed, 483 insertions(+) create mode 100644 scripts/item-descriptions.lua create mode 100644 scripts/view-item-info.lua diff --git a/NEWS b/NEWS index 3d5be83aa..0fd319bee 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ DFHack Future New internal commands New plugins New scripts + view-item-info: adds information and customisable descriptions to item viewscreens New tweaks New features Fixes diff --git a/Readme.rst b/Readme.rst index 9d071bd3b..bcd947926 100644 --- a/Readme.rst +++ b/Readme.rst @@ -2573,6 +2573,17 @@ undump-buildings ================ Undesignates building base materials for dumping. +view-item-info +============== +A script to extend the item or unit viewscreen with additional information +including a custom description of each item (when available), and properties +such as material statistics, weapon attacks, armor effectiveness, and more. + +The associated script ``item-descriptions.lua`` supplies custom descriptions +of items. Individual descriptions can be added or overridden by a similar +script ``raw/scripts/more-item-descriptions.lua``. Both work as sparse lists, +so missing items simply go undescribed if not defined in the fallback. + ======== modtools ======== diff --git a/dfhack.init-example b/dfhack.init-example index 1bb3f8acf..c16a441f1 100644 --- a/dfhack.init-example +++ b/dfhack.init-example @@ -229,6 +229,9 @@ soundsense-season # write identifying information about the fort to gamelog on world load log-region +# add information to item viewscreens +view-item-info + ####################################################### # Apply binary patches at runtime # ####################################################### diff --git a/scripts/item-descriptions.lua b/scripts/item-descriptions.lua new file mode 100644 index 000000000..720d6d1ab --- /dev/null +++ b/scripts/item-descriptions.lua @@ -0,0 +1,88 @@ +-- Holds custom descriptions for view-item-info +-- By PeridexisErrant + +if not moduleMode then + print("scripts/item-descriptions.lua is a content library; calling it does nothing.") +end + +--[[ +This script has a single function: to return a custom description for every +vanilla item in the game. + +Having this as a separate script to "view-item-info.lua" allows either mods +to partially or fully replace the content. + +If "raw/scripts/item-descriptions.lua" exists, it will entirely replace this one. +Instead, use "raw/scripts/more-item-descriptions.lua" to add content, or replace +descriptions on a case-by-case basis. If an item description cannot be found in +the latter script, view-item-info will fall back to the former. + +Lines should be about 70 characters for consistent presentation and to fit +on-screen. Logical sections can be separated by an empty line (""). +Text blocks should use identical indentation to make formatting clearly visible. + +All described vanilla item IDs: + +"ANVIL", "ARMORSTAND", "BARREL", "BED", "BIN", "BOX", "BUCKET", "ITEM_AMMO_ARROWS", "ITEM_AMMO_BOLTS", "ITEM_ARMOR_LEATHER", "ITEM_WEAPON_PICK", "ITEM_WEAPON_AXE_BATTLE", "ITEM_WEAPON_AXE_TRAINING", "SLAB", "TRAPPARTS", + + +Remaining item IDs: + +"AMULET", "ANIMALTRAP", "BACKPACK", "BALLISTAARROWHEAD", "BALLISTAPARTS", "BAR", "BLOCKS", "BOOK", "BOULDER", "BRACELET", "CABINET", "CAGE", "CATAPULTPARTS", "CHAIN", "CHAIR", "CLOTH", "COFFIN", "COIN", "CROWN", "CRUTCH", "DOOR", "EARRING", "FIGURINE", "FLASK", "FLOODGATE", "GOBLET", "GRATE", "HATCH_COVER", "ITEM_ARMOR_BREASTPLATE", "ITEM_ARMOR_CAPE", "ITEM_ARMOR_CLOAK", "ITEM_ARMOR_COAT", "ITEM_ARMOR_DRESS", "ITEM_ARMOR_MAIL_SHIRT", "ITEM_ARMOR_ROBE", "ITEM_ARMOR_SHIRT", "ITEM_ARMOR_TOGA", "ITEM_ARMOR_TUNIC", "ITEM_ARMOR_VEST", "ITEM_FOOD_BISCUITS", "ITEM_FOOD_ROAST", "ITEM_FOOD_STEW", "ITEM_GLOVES_GAUNTLETS", "ITEM_GLOVES_GLOVES", "ITEM_GLOVES_MITTENS", "ITEM_HELM_CAP", "ITEM_HELM_HELM", "ITEM_HELM_HOOD", "ITEM_HELM_MASK", "ITEM_HELM_SCARF_HEAD", "ITEM_HELM_TURBAN", "ITEM_HELM_VEIL_FACE", "ITEM_HELM_VEIL_HEAD", "ITEM_INSTRUMENT_DRUM", "ITEM_INSTRUMENT_FLUTE", "ITEM_INSTRUMENT_HARP", "ITEM_INSTRUMENT_PICCOLO", "ITEM_INSTRUMENT_TRUMPET", "ITEM_PANTS_BRAIES", "ITEM_PANTS_GREAVES", "ITEM_PANTS_LEGGINGS", "ITEM_PANTS_LOINCLOTH", "ITEM_PANTS_PANTS", "ITEM_PANTS_SKIRT", "ITEM_PANTS_SKIRT_LONG", "ITEM_PANTS_SKIRT_SHORT", "ITEM_PANTS_THONG", "ITEM_SHIELD_BUCKLER", "ITEM_SHIELD_SHIELD", "ITEM_SHOES_BOOTS", "ITEM_SHOES_BOOTS_LOW", "ITEM_SHOES_CHAUSSE", "ITEM_SHOES_SANDAL", "ITEM_SHOES_SHOES", "ITEM_SHOES_SOCKS", "ITEM_SIEGEAMMO_BALLISTA", "ITEM_TOOL_BOWL", "ITEM_TOOL_CAULDRON", "ITEM_TOOL_FORK_CARVING", "ITEM_TOOL_HIVE", "ITEM_TOOL_HONEYCOMB", "ITEM_TOOL_JUG", "ITEM_TOOL_KNIFE_BONING", "ITEM_TOOL_KNIFE_CARVING", "ITEM_TOOL_KNIFE_MEAT_CLEAVER", "ITEM_TOOL_KNIFE_SLICING", "ITEM_TOOL_LADLE", "ITEM_TOOL_LARGE_POT", "ITEM_TOOL_MINECART", "ITEM_TOOL_MORTAR", "ITEM_TOOL_NEST_BOX", "ITEM_TOOL_PESTLE", "ITEM_TOOL_POUCH", "ITEM_TOOL_SCALE_SHARD", "ITEM_TOOL_STEPLADDER", "ITEM_TOOL_WHEELBARROW", "ITEM_TOY_AXE", "ITEM_TOY_BOAT", "ITEM_TOY_HAMMER", "ITEM_TOY_MINIFORGE", "ITEM_TOY_PUZZLEBOX", "ITEM_TRAPCOMP_ENORMOUSCORKSCREW", "ITEM_TRAPCOMP_GIANTAXEBLADE", "ITEM_TRAPCOMP_LARGESERRATEDDISC", "ITEM_TRAPCOMP_MENACINGSPIKE", "ITEM_TRAPCOMP_SPIKEDBALL", "ITEM_WEAPON_AXE_GREAT", "ITEM_WEAPON_BLOWGUN", "ITEM_WEAPON_BOW", "ITEM_WEAPON_CROSSBOW", "ITEM_WEAPON_DAGGER_LARGE", "ITEM_WEAPON_FLAIL", "ITEM_WEAPON_HALBERD", "ITEM_WEAPON_HAMMER_WAR", "ITEM_WEAPON_MACE", "ITEM_WEAPON_MAUL", "ITEM_WEAPON_MORNINGSTAR", "ITEM_WEAPON_PIKE", "ITEM_WEAPON_SCIMITAR", "ITEM_WEAPON_SCOURGE", "ITEM_WEAPON_SPEAR", "ITEM_WEAPON_SPEAR_TRAINING", "ITEM_WEAPON_SWORD_2H", "ITEM_WEAPON_SWORD_LONG", "ITEM_WEAPON_SWORD_SHORT", "ITEM_WEAPON_SWORD_SHORT_TRAINING", "ITEM_WEAPON_WHIP", "MEAT", "MILLSTONE", "ORTHOPEDIC_CAST", "PIPE_SECTION", "QUERN", "QUIVER", "RING", "ROCK", "ROUGH", "SCEPTER", "SKIN_TANNED", "SMALLGEM", "SPLINT", "STATUE", "TABLE", "THREAD", "TOTEM", "TRACTION_BENCH", "WEAPONRACK", "WINDOW", "WOOD" + +]] + +descriptions = { + ANVIL = { "An essential component of the forge."}, + ARMORSTAND = { + "A rack for the storage of military equipment, specifically armor.", + "It is required by some nobles, and can be used to create a barracks."}, + BARREL = { "A hollow cylinder with a removable lid. It is used to hold liquids,", + "food, and seeds. It can be made from metal or wood, and is replaceable", + "with a rock pot. A barrel (or rock pot) is needed to brew drinks."}, + BED = { "A pallet for dwarves to sleep on, which must be made from wood.", + "It prevents the stress of sleeping on the ground, and can be used", + "to designate a bedroom (used by one dwarf or couple), a dormitory", + "(used by multiple dwarves), or a barracks (used by a military", + "squad for training or sleep)."}, + BIN = { "A container for the storage of ammunition, armor and weapons, bars,", + "blocks, cloth and leather, coins, finished goods and gems. It can", + "be used to carry multiple items to the Trade Depot at once.", + "A bin can be made from wood or forged from metal."}, + BOX = { "A container for storing dwarves' items. They are required by nobles,", + "and will increase the value of rooms they are placed in. Also", + "required to store hospital supplies. They can be made from stone or", + "metal (coffers), wood (chests),or textiles or leather (bags)."}, + BUCKET = { "A small cylindrical or conical container for holding and carrying", + "small amounts of liquid such as water or lye. They are used by", + "dwarves to give water to other dwarves, to store lye, and are", + "required to build wells and certain workshops. They can be made", + "from wood or metal."}, + ITEM_AMMO_ARROWS = { + "Ammunition for bows."}, + ITEM_AMMO_BOLTS = { + "Ammunition for crossbows."}, + ITEM_ARMOR_LEATHER = { + "Leather armor is light and covers both arms and legs", + "in addition to body"}, + ITEM_WEAPON_PICK = { + "The most important item for a beginning fortress, a pick can", + "get a party underground. Also crucial mining for stone or", + "metals, expansion of living space, and so on.", "", + "A pick is also useful as a weapon, though putting miners in the", + "military causes equipment clashes."}, + ITEM_WEAPON_AXE_BATTLE = { + "A battle axe is an edged weapon: essentially a sharp blade", + "mounted along the end of a short and heavy handle.", "", + "Dwarves can forge battle axes out of any weapon-grade metal,", + "though those with superior edge properties are more effective.", "", + "A battle axe may also be used as a tool for chopping down trees."}, + ITEM_WEAPON_AXE_TRAINING = { + "As a battleaxe made from wood, this practise weapon is useful for", + "training recruits. Thanks to good craftsdwarfship, it can also", + "be used to cut down trees."}, + SLAB = { "A memorial stone, used to quiet restless ghost when engraved with", + "the name of the deceased and built."}, + TRAPPARTS = { + "Used to build traps, levers and other machines."} +} diff --git a/scripts/view-item-info.lua b/scripts/view-item-info.lua new file mode 100644 index 000000000..57bc4d11e --- /dev/null +++ b/scripts/view-item-info.lua @@ -0,0 +1,380 @@ +-- Extended Item Viewscreens +-- Shows information on material properties, weapon or armour stats, and more. +-- By PeridexisErrant, adapted from nb_item_info by Raidau + +local help = [[Extended Item Viewscreen + +A script to extend the item or unit viewscreen with additional information +including properties such as material info, weapon and attack properties, +armor thickness and coverage, and more - including custom item descriptions.]] + +function isInList(list, item) + for k,v in pairs (list) do + if item == v then + return true + end + end +end + +local args = {...} +local lastframe = df.global.enabler.frame_last +if isInList(args, "help") or isInList(args, "?") then + print(help) return +end +print ("view-item-info enabled") + +function append (list, str, indent) + local str = str or " " + local indent = indent or 0 + table.insert(list, {str, indent * 4}) +end + +function add_lines_to_list(t1,t2) + for i=1,#t2 do + t1[#t1+1] = t2[i] + end + return t1 +end + +function GetMatPlant (item) + if dfhack.matinfo.decode(item).mode == "plant" then + return dfhack.matinfo.decode(item).plant + end +end + +function get_textid (item) + return string.match(tostring(item._type),""):upper() +end + +function compare_iron (mat_prop, iron_prop) + return " "..mat_prop.." ("..math.floor(mat_prop/iron_prop*100).."% of iron)" +end + +function GetMatPropertiesStringList (item) + local mat = dfhack.matinfo.decode(item).material + local list = {} + local deg_U = item.temperature.whole + local deg_C = math.floor((deg_U-10000)*5/9) + append(list,"Temperature: "..deg_C.."\248C ("..deg_U.."U)") + append(list,"Color: "..df.global.world.raws.language.colors[mat.state_color.Solid].name) + local function GetStrainDescription (number) + if tonumber(number) >= 50000 then return "very elastic" + elseif tonumber(number) < 50000 then return "elastic" + elseif tonumber(number) < 15001 then return "medium" + elseif tonumber(number) < 5001 then return "stiff" + elseif tonumber(number) < 1000 then return "very stiff" + elseif tonumber(number) < 1 then return "crystalline" + else return "unknown" end + end + local mat_properties_for = {"BAR", "SMALLGEM", "BOULDER", "ROUGH", + "WOOD", "GEM", "ANVIL", "THREAD", "SHOES", "CLOTH", "ROCK", "WEAPON", "TRAPCOMP", + "ORTHOPEDIC_CAST", "SIEGEAMMO", "SHIELD", "PANTS", "HELM", "GLOVES", "ARMOR", "AMMO"} + if isInList(mat_properties_for, get_textid (item)) then + append(list,"Material name: "..mat.state_name.Solid) + append(list,"Material properties: ") + append(list,"Solid density: "..mat.solid_density..'g/cm^3',1) + local maxedge = mat.strength.max_edge + append(list,"Maximum sharpness: "..maxedge.." ("..maxedge/standard.strength.max_edge*100 .."%)",1) + if mat.molar_mass > 0 then + append(list,"Molar mass: "..mat.molar_mass,1) + end + append(list,"Shear strength:",1) + append(list, "yield:"..compare_iron(mat.strength.yield.SHEAR, standard.strength.yield.SHEAR), 2) + append(list, "fracture:"..compare_iron(mat.strength.fracture.SHEAR, standard.strength.fracture.SHEAR), 2) + local s_strain = mat.strength.strain_at_yield.SHEAR + append(list, "elasticity: "..s_strain.." ("..GetStrainDescription(s_strain)..")", 2) + append(list,"Impact strength:",1) + append(list, "yield:"..compare_iron(mat.strength.yield.IMPACT, standard.strength.yield.IMPACT), 2) + append(list, "fracture:"..compare_iron(mat.strength.fracture.IMPACT, standard.strength.fracture.IMPACT), 2) + local i_strain = mat.strength.strain_at_yield.IMPACT + append(list, "elasticity: "..i_strain.." ("..GetStrainDescription(i_strain)..")", 2) + end + append(list) + return list +end + +function GetArmorPropertiesStringList (item) + local mat = dfhack.matinfo.decode(item).material + local list = {} + append(list,"Armor properties: ") + append(list,"Thickness: "..item.subtype.props.layer_size,1) + append(list,"Coverage: "..item.subtype.props.coverage.."%",1) + append(list,"Fit for "..df.creature_raw.find(item.maker_race).name[0],1) + append(list) + return list +end + +function GetShieldPropertiesStringList (item) + local mat = dfhack.matinfo.decode(item).material + local list = {} + append(list,"Shield properties:") + append(list,"Base block chance: "..item.subtype.blockchance,1) + append(list,"Fit for "..df.creature_raw.find(item.maker_race).name[0],1) + append(list) + return list +end + +function GetWeaponPropertiesStringList (item) + local mat = dfhack.matinfo.decode(item).material + local list = {} + append(list) + if item._type == df.item_toolst and #item.subtype.attacks < 1 then + return list + end + append(list,"Weapon properties: ") + if item.sharpness > 0 then + append(list,"Sharpness:"..compare_iron(item.sharpness, standard.strength.max_edge),1) + else + append(list,"Not edged",1) + end + if string.len(item.subtype.ranged_ammo) > 0 then + append(list,"Ranged weapon",1) + append(list,"Ammo: "..item.subtype.ranged_ammo:lower(),2) + if item.subtype.shoot_force > 0 then + append(list,"Shoot force: "..item.subtype.shoot_force,2) + end + if item.subtype.shoot_maxvel > 0 then + append(list,"Maximum projectile velocity: "..item.subtype.shoot_maxvel,2) + end + end + append(list,"Required size: "..item.subtype.minimum_size*10,1) + if item.subtype.two_handed*10 > item.subtype.minimum_size*10 then + append(list,"Used as 2-handed until unit size: "..item.subtype.two_handed*10,2) + end + append(list,"Attacks: ",1) + for k,attack in pairs (item.subtype.attacks) do + local name = attack.verb_2nd + if attack.noun ~= "NO_SUB" then + name = name.." with "..attack.noun + end + if attack.edged then + name = name.." (edged)" + else + name = name.." (blunt)" + end + append(list,name,2) + append(list,"Contact area: "..attack.contact,3) + if attack.edged then + append(list,"Penetration: "..attack.penetration,3) + end + append(list,"Velocity multiplier: "..attack.velocity_mult/1000,3) + if attack.flags.bad_multiattack then + append(list,"Bad multiattack",3) + end + append(list,"Prepare "..attack.prepare.." / recover "..attack.recover,3) + end + append(list) + return list +end + +function GetAmmoPropertiesStringList (item) + local mat = dfhack.matinfo.decode(item).material + local list = {} + append(list) + if item._type == df.item_toolst and #item.subtype.attacks < 1 then + return list + end + append(list,"Ammo properties: ") + if item.sharpness > 0 then + append(list,"Sharpness: "..item.sharpness,1) + else + append(list,"Not edged",1) + end + append(list,"Attacks: ", 1) + for k,attack in pairs (item.subtype.attacks) do + local name = attack.verb_2nd + if attack.noun ~= "NO_SUB" then + name = name.." with "..attack.noun + end + if attack.edged then + name = name.." (edged)" + else + name = name.." (blunt)" + end + append(list,name,2) + append(list,"Contact area: "..attack.contact,3) + if attack.edged then + append(list,"Penetration: "..attack.penetration,3) + end + append(list,"Velocity multiplier: "..attack.velocity_mult/1000,3) + if attack.flags.bad_multiattack then + append(list,"Bad multiattack",3) + end + append(list,"Prepare "..attack.prepare.." / recover "..attack.recover,3) + end + append(list) + return list +end + +function edible_string (mat) + local edible_string = "Edible" + if mat.flags.EDIBLE_RAW or mat.flags.EDIBLE_COOKED then + if mat.flags.EDIBLE_RAW then + edible_string = edible_string.." raw" + if mat.flags.EDIBLE_COOKED then + edible_string = edible_string.." and cooked" + end + elseif mat.flags.EDIBLE_COOKED then + edible_string = edible_string.." only when cooked" + end + else + edible_string = "Not edible" + end + return edible_string +end + +function GetReactionProduct (inmat, reaction) + for k,v in pairs (inmat.reaction_product.id) do + if v.value == reaction then + return {inmat.reaction_product.material.mat_type[k], + inmat.reaction_product.material.mat_index[k]} + end + end +end + +function add_react_prod (list, mat, product, str) + local mat_type, mat_index = GetReactionProduct (mat, product) + if mat_type then + local result = dfhack.matinfo.decode(mat_type, mat_index).material.state_name.Liquid + append(list, str..result) + end +end + +function get_plant_reaction_products (mat) + local list = {} + add_react_prod (list, mat, "DRINK_MAT", "Used to brew ") + add_react_prod (list, mat, "GROWTH_JUICE_PROD", "Pressed into ") + add_react_prod (list, mat, "PRESS_LIQUID_MAT", "Pressed into ") + add_react_prod (list, mat, "LIQUID_EXTRACTABLE", "Extractable product: ") + add_react_prod (list, mat, "WATER_SOLUTION_PROD", "Can be mixed with water to make ") + add_react_prod (list, mat, "RENDER_MAT", "Rendered into ") + add_react_prod (list, mat, "SOAP_MAT", "Used to make soap") + if GetReactionProduct (mat, "SUGARABLE") then + append(list,"Used to make sugar") + end + if GetReactionProduct (mat, "MILLABLE") or + GetReactionProduct (mat, "GRAIN_MILLABLE") or + GetReactionProduct (mat, "GROWTH_MILLABLE") then + append(list,"Can be milled") + end + if GetReactionProduct(mat, "GRAIN_THRESHABLE") then + append(list,"Grain can be threshed") + end + if GetReactionProduct (mat, "CHEESE_MAT") then + local mat_type, mat_index = GetReactionProduct (mat, "CHEESE_MAT") + append(list,"Used to make "..dfhack.matinfo.decode(mat_type, mat_index).material.state_name.Solid) + end + return list +end + +function GetFoodPropertiesStringList (item) + local mat = dfhack.matinfo.decode(item).material + local list = {{" ", 0}} + append(list,edible_string(mat)) + if item._type == df.item_foodst then + append(list,"This is prepared meal") + append(list) + return list + end + if mat == dfhack.matinfo.find ("WATER") then + append(list,"Water is drinkable") + append(list) + return list + end + add_lines_to_list(list, get_plant_reaction_products(mat)) + if item._type == df.item_plantst and GetMatPlant (item) then + local plant = GetMatPlant (item) + for k,v in pairs (plant.material_defs) do + if v ~= -1 and string.find (k,"type_") and not string.find (k,"type_basic") + or string.find (k,"type_seed") or string.find (k,"type_tree") then + local targetmat = dfhack.matinfo.decode (v, + plant.material_defs["idx_"..string.match (k,"type_(.+)")]) + local state = "Liquid" + if string.find (k,"type_mill") then state = "Powder" + elseif string.find (k,"type_thread") then state = "Solid" end + local st_name = targetmat.material.state_name[state] + append(list,"Used to make "..targetmat.material.prefix..''..st_name) + end + end + end + append(list) + return list +end + +function get_all_uses_strings (item) + local all_lines = {} + local FoodsAndPlants = {df.item_meatst, df.item_globst, + df.item_plantst, df.item_plant_growthst, df.item_liquid_miscst, + df.item_powder_miscst, df.item_cheesest, df.item_foodst} + local ArmourTypes = {df.item_armorst, df.item_pantsst, + df.item_helmst, df.item_glovesst, df.item_shoesst} + if df.global.gamemode == df.game_mode.ADVENTURE and item ~= "COIN" then + add_lines_to_list(all_lines, {{"Value: "..dfhack.items.getValue(item),0}}) + elseif isInList(ArmourTypes, item._type) then + add_lines_to_list(all_lines, GetArmorPropertiesStringList(item)) + elseif item._type == df.item_weaponst or item._type == df.item_toolst then + add_lines_to_list(all_lines, GetWeaponPropertiesStringList(item)) + elseif item._type == df.item_ammost then + add_lines_to_list(all_lines, GetAmmoPropertiesStringList(item)) + elseif item._type == df.item_shieldst then + add_lines_to_list(all_lines, GetShieldPropertiesStringList(item)) + elseif item._type == df.item_seedsst then + local str = math.floor(GetMatPlant(item).growdur/12).." days" + add_lines_to_list(all_lines, {{"Growth time: "..str, 0}}) + elseif isInList(FoodsAndPlants, item._type) then + add_lines_to_list(all_lines, GetFoodPropertiesStringList(item)) + end + if not dfhack.items.isCasteMaterial(df.item_type[get_textid(item)]) then + add_lines_to_list(all_lines, GetMatPropertiesStringList(item)) + end + return all_lines +end + +function get_custom_item_desc (item) + local desc + local ID = get_textid (item) + if ID and dfhack.items.getSubtypeCount(df.item_type[ID]) ~= -1 then + ID = item.subtype.id end + if not ID then return nil end + if dfhack.findScript("item-descriptions") then + local desc = dfhack.script_environment("item-descriptions").descriptions.ID + end + if dfhack.findScript("more-item-descriptions") then + local desc = dfhack.script_environment("more-item-descriptions").descriptions.ID or desc + end + if desc then add_lines_to_list(desc, {""}) end + return desc +end + +function AddUsesString (viewscreen,line,indent) + local str = df.new("string") + str.value = tostring(line) + local indent = indent or 0 + viewscreen.entry_ref:insert('#', nil) + viewscreen.entry_indent:insert('#', indent) + viewscreen.unk_34:insert('#', nil) -- TODO: get this into structures, and fix usage! + viewscreen.entry_string:insert('#', str) + viewscreen.entry_reaction:insert('#', -1) +end + +function dfhack.onStateChange.item_info (code) + if code == SC_VIEWSCREEN_CHANGED and dfhack.isWorldLoaded() then + standard = dfhack.matinfo.find("INORGANIC:IRON").material + if not standard then return end + local scr = dfhack.gui.getCurViewscreen() + if scr._type == df.viewscreen_itemst then + if #scr.entry_string > 0 and scr.entry_string[#scr.entry_string-1].value == " " then + return + end + local description = get_custom_item_desc (scr.item) or "" + for i = 1, #description do + AddUsesString(scr,description[i]) + end + local all_lines = get_all_uses_strings (scr.item) + for i = 1, #all_lines do + AddUsesString(scr,all_lines[i][1],all_lines[i][2]) + end + scr.caption_uses = true + end + end +end From 2bd5b7e349429aa8f6d11f95be635033414e7a19 Mon Sep 17 00:00:00 2001 From: Peridexis Errant Date: Mon, 6 Apr 2015 16:03:14 +1000 Subject: [PATCH 2/2] Describe blocks, fix trailing whitespace --- scripts/item-descriptions.lua | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/item-descriptions.lua b/scripts/item-descriptions.lua index 720d6d1ab..7d1b3d4e8 100644 --- a/scripts/item-descriptions.lua +++ b/scripts/item-descriptions.lua @@ -23,12 +23,12 @@ Text blocks should use identical indentation to make formatting clearly visible. All described vanilla item IDs: -"ANVIL", "ARMORSTAND", "BARREL", "BED", "BIN", "BOX", "BUCKET", "ITEM_AMMO_ARROWS", "ITEM_AMMO_BOLTS", "ITEM_ARMOR_LEATHER", "ITEM_WEAPON_PICK", "ITEM_WEAPON_AXE_BATTLE", "ITEM_WEAPON_AXE_TRAINING", "SLAB", "TRAPPARTS", +"ANVIL", "ARMORSTAND", "BARREL", "BED", "BIN", "BLOCKS", "BOX", "BUCKET", "ITEM_AMMO_ARROWS", "ITEM_AMMO_BOLTS", "ITEM_ARMOR_LEATHER", "ITEM_WEAPON_PICK", "ITEM_WEAPON_AXE_BATTLE", "ITEM_WEAPON_AXE_TRAINING", "SLAB", "TRAPPARTS" -Remaining item IDs: +Remaining item IDs: -"AMULET", "ANIMALTRAP", "BACKPACK", "BALLISTAARROWHEAD", "BALLISTAPARTS", "BAR", "BLOCKS", "BOOK", "BOULDER", "BRACELET", "CABINET", "CAGE", "CATAPULTPARTS", "CHAIN", "CHAIR", "CLOTH", "COFFIN", "COIN", "CROWN", "CRUTCH", "DOOR", "EARRING", "FIGURINE", "FLASK", "FLOODGATE", "GOBLET", "GRATE", "HATCH_COVER", "ITEM_ARMOR_BREASTPLATE", "ITEM_ARMOR_CAPE", "ITEM_ARMOR_CLOAK", "ITEM_ARMOR_COAT", "ITEM_ARMOR_DRESS", "ITEM_ARMOR_MAIL_SHIRT", "ITEM_ARMOR_ROBE", "ITEM_ARMOR_SHIRT", "ITEM_ARMOR_TOGA", "ITEM_ARMOR_TUNIC", "ITEM_ARMOR_VEST", "ITEM_FOOD_BISCUITS", "ITEM_FOOD_ROAST", "ITEM_FOOD_STEW", "ITEM_GLOVES_GAUNTLETS", "ITEM_GLOVES_GLOVES", "ITEM_GLOVES_MITTENS", "ITEM_HELM_CAP", "ITEM_HELM_HELM", "ITEM_HELM_HOOD", "ITEM_HELM_MASK", "ITEM_HELM_SCARF_HEAD", "ITEM_HELM_TURBAN", "ITEM_HELM_VEIL_FACE", "ITEM_HELM_VEIL_HEAD", "ITEM_INSTRUMENT_DRUM", "ITEM_INSTRUMENT_FLUTE", "ITEM_INSTRUMENT_HARP", "ITEM_INSTRUMENT_PICCOLO", "ITEM_INSTRUMENT_TRUMPET", "ITEM_PANTS_BRAIES", "ITEM_PANTS_GREAVES", "ITEM_PANTS_LEGGINGS", "ITEM_PANTS_LOINCLOTH", "ITEM_PANTS_PANTS", "ITEM_PANTS_SKIRT", "ITEM_PANTS_SKIRT_LONG", "ITEM_PANTS_SKIRT_SHORT", "ITEM_PANTS_THONG", "ITEM_SHIELD_BUCKLER", "ITEM_SHIELD_SHIELD", "ITEM_SHOES_BOOTS", "ITEM_SHOES_BOOTS_LOW", "ITEM_SHOES_CHAUSSE", "ITEM_SHOES_SANDAL", "ITEM_SHOES_SHOES", "ITEM_SHOES_SOCKS", "ITEM_SIEGEAMMO_BALLISTA", "ITEM_TOOL_BOWL", "ITEM_TOOL_CAULDRON", "ITEM_TOOL_FORK_CARVING", "ITEM_TOOL_HIVE", "ITEM_TOOL_HONEYCOMB", "ITEM_TOOL_JUG", "ITEM_TOOL_KNIFE_BONING", "ITEM_TOOL_KNIFE_CARVING", "ITEM_TOOL_KNIFE_MEAT_CLEAVER", "ITEM_TOOL_KNIFE_SLICING", "ITEM_TOOL_LADLE", "ITEM_TOOL_LARGE_POT", "ITEM_TOOL_MINECART", "ITEM_TOOL_MORTAR", "ITEM_TOOL_NEST_BOX", "ITEM_TOOL_PESTLE", "ITEM_TOOL_POUCH", "ITEM_TOOL_SCALE_SHARD", "ITEM_TOOL_STEPLADDER", "ITEM_TOOL_WHEELBARROW", "ITEM_TOY_AXE", "ITEM_TOY_BOAT", "ITEM_TOY_HAMMER", "ITEM_TOY_MINIFORGE", "ITEM_TOY_PUZZLEBOX", "ITEM_TRAPCOMP_ENORMOUSCORKSCREW", "ITEM_TRAPCOMP_GIANTAXEBLADE", "ITEM_TRAPCOMP_LARGESERRATEDDISC", "ITEM_TRAPCOMP_MENACINGSPIKE", "ITEM_TRAPCOMP_SPIKEDBALL", "ITEM_WEAPON_AXE_GREAT", "ITEM_WEAPON_BLOWGUN", "ITEM_WEAPON_BOW", "ITEM_WEAPON_CROSSBOW", "ITEM_WEAPON_DAGGER_LARGE", "ITEM_WEAPON_FLAIL", "ITEM_WEAPON_HALBERD", "ITEM_WEAPON_HAMMER_WAR", "ITEM_WEAPON_MACE", "ITEM_WEAPON_MAUL", "ITEM_WEAPON_MORNINGSTAR", "ITEM_WEAPON_PIKE", "ITEM_WEAPON_SCIMITAR", "ITEM_WEAPON_SCOURGE", "ITEM_WEAPON_SPEAR", "ITEM_WEAPON_SPEAR_TRAINING", "ITEM_WEAPON_SWORD_2H", "ITEM_WEAPON_SWORD_LONG", "ITEM_WEAPON_SWORD_SHORT", "ITEM_WEAPON_SWORD_SHORT_TRAINING", "ITEM_WEAPON_WHIP", "MEAT", "MILLSTONE", "ORTHOPEDIC_CAST", "PIPE_SECTION", "QUERN", "QUIVER", "RING", "ROCK", "ROUGH", "SCEPTER", "SKIN_TANNED", "SMALLGEM", "SPLINT", "STATUE", "TABLE", "THREAD", "TOTEM", "TRACTION_BENCH", "WEAPONRACK", "WINDOW", "WOOD" +"AMULET", "ANIMALTRAP", "BACKPACK", "BALLISTAARROWHEAD", "BALLISTAPARTS", "BAR", "BOOK", "BOULDER", "BRACELET", "CABINET", "CAGE", "CATAPULTPARTS", "CHAIN", "CHAIR", "CLOTH", "COFFIN", "COIN", "CROWN", "CRUTCH", "DOOR", "EARRING", "FIGURINE", "FLASK", "FLOODGATE", "GOBLET", "GRATE", "HATCH_COVER", "ITEM_ARMOR_BREASTPLATE", "ITEM_ARMOR_CAPE", "ITEM_ARMOR_CLOAK", "ITEM_ARMOR_COAT", "ITEM_ARMOR_DRESS", "ITEM_ARMOR_MAIL_SHIRT", "ITEM_ARMOR_ROBE", "ITEM_ARMOR_SHIRT", "ITEM_ARMOR_TOGA", "ITEM_ARMOR_TUNIC", "ITEM_ARMOR_VEST", "ITEM_FOOD_BISCUITS", "ITEM_FOOD_ROAST", "ITEM_FOOD_STEW", "ITEM_GLOVES_GAUNTLETS", "ITEM_GLOVES_GLOVES", "ITEM_GLOVES_MITTENS", "ITEM_HELM_CAP", "ITEM_HELM_HELM", "ITEM_HELM_HOOD", "ITEM_HELM_MASK", "ITEM_HELM_SCARF_HEAD", "ITEM_HELM_TURBAN", "ITEM_HELM_VEIL_FACE", "ITEM_HELM_VEIL_HEAD", "ITEM_INSTRUMENT_DRUM", "ITEM_INSTRUMENT_FLUTE", "ITEM_INSTRUMENT_HARP", "ITEM_INSTRUMENT_PICCOLO", "ITEM_INSTRUMENT_TRUMPET", "ITEM_PANTS_BRAIES", "ITEM_PANTS_GREAVES", "ITEM_PANTS_LEGGINGS", "ITEM_PANTS_LOINCLOTH", "ITEM_PANTS_PANTS", "ITEM_PANTS_SKIRT", "ITEM_PANTS_SKIRT_LONG", "ITEM_PANTS_SKIRT_SHORT", "ITEM_PANTS_THONG", "ITEM_SHIELD_BUCKLER", "ITEM_SHIELD_SHIELD", "ITEM_SHOES_BOOTS", "ITEM_SHOES_BOOTS_LOW", "ITEM_SHOES_CHAUSSE", "ITEM_SHOES_SANDAL", "ITEM_SHOES_SHOES", "ITEM_SHOES_SOCKS", "ITEM_SIEGEAMMO_BALLISTA", "ITEM_TOOL_BOWL", "ITEM_TOOL_CAULDRON", "ITEM_TOOL_FORK_CARVING", "ITEM_TOOL_HIVE", "ITEM_TOOL_HONEYCOMB", "ITEM_TOOL_JUG", "ITEM_TOOL_KNIFE_BONING", "ITEM_TOOL_KNIFE_CARVING", "ITEM_TOOL_KNIFE_MEAT_CLEAVER", "ITEM_TOOL_KNIFE_SLICING", "ITEM_TOOL_LADLE", "ITEM_TOOL_LARGE_POT", "ITEM_TOOL_MINECART", "ITEM_TOOL_MORTAR", "ITEM_TOOL_NEST_BOX", "ITEM_TOOL_PESTLE", "ITEM_TOOL_POUCH", "ITEM_TOOL_SCALE_SHARD", "ITEM_TOOL_STEPLADDER", "ITEM_TOOL_WHEELBARROW", "ITEM_TOY_AXE", "ITEM_TOY_BOAT", "ITEM_TOY_HAMMER", "ITEM_TOY_MINIFORGE", "ITEM_TOY_PUZZLEBOX", "ITEM_TRAPCOMP_ENORMOUSCORKSCREW", "ITEM_TRAPCOMP_GIANTAXEBLADE", "ITEM_TRAPCOMP_LARGESERRATEDDISC", "ITEM_TRAPCOMP_MENACINGSPIKE", "ITEM_TRAPCOMP_SPIKEDBALL", "ITEM_WEAPON_AXE_GREAT", "ITEM_WEAPON_BLOWGUN", "ITEM_WEAPON_BOW", "ITEM_WEAPON_CROSSBOW", "ITEM_WEAPON_DAGGER_LARGE", "ITEM_WEAPON_FLAIL", "ITEM_WEAPON_HALBERD", "ITEM_WEAPON_HAMMER_WAR", "ITEM_WEAPON_MACE", "ITEM_WEAPON_MAUL", "ITEM_WEAPON_MORNINGSTAR", "ITEM_WEAPON_PIKE", "ITEM_WEAPON_SCIMITAR", "ITEM_WEAPON_SCOURGE", "ITEM_WEAPON_SPEAR", "ITEM_WEAPON_SPEAR_TRAINING", "ITEM_WEAPON_SWORD_2H", "ITEM_WEAPON_SWORD_LONG", "ITEM_WEAPON_SWORD_SHORT", "ITEM_WEAPON_SWORD_SHORT_TRAINING", "ITEM_WEAPON_WHIP", "MEAT", "MILLSTONE", "ORTHOPEDIC_CAST", "PIPE_SECTION", "QUERN", "QUIVER", "RING", "ROCK", "ROUGH", "SCEPTER", "SKIN_TANNED", "SMALLGEM", "SPLINT", "STATUE", "TABLE", "THREAD", "TOTEM", "TRACTION_BENCH", "WEAPONRACK", "WINDOW", "WOOD" ]] @@ -49,6 +49,10 @@ descriptions = { "blocks, cloth and leather, coins, finished goods and gems. It can", "be used to carry multiple items to the Trade Depot at once.", "A bin can be made from wood or forged from metal."}, + BLOCKS = { "Blocks can be used for constructions in place of raw materials such", + "as logs or bars. Cutting boulders into blocks gives four times as", + "many items, all of which are lighter for faster hauling and yield", + "smooth constructions."}, BOX = { "A container for storing dwarves' items. They are required by nobles,", "and will increase the value of rooms they are placed in. Also", "required to store hospital supplies. They can be made from stone or", @@ -59,9 +63,10 @@ descriptions = { "required to build wells and certain workshops. They can be made", "from wood or metal."}, ITEM_AMMO_ARROWS = { - "Ammunition for bows."}, + "Ammunition for bows, which are primarily used by elves."}, ITEM_AMMO_BOLTS = { - "Ammunition for crossbows."}, + "Ammunition for crossbows, which are a dwarf's preferred ranged weapon.", + "It is not recommended to store bolts in bins, due to pickup bugs."}, ITEM_ARMOR_LEATHER = { "Leather armor is light and covers both arms and legs", "in addition to body"},