From a8f810cc3bf740454e8982bd8003c09522e31de6 Mon Sep 17 00:00:00 2001 From: expwnent Date: Wed, 9 Jul 2014 06:21:52 -0400 Subject: [PATCH] Lots of tweaks. --- NEWS | 34 +-- library/lua/repeat-util.lua | 1 + library/lua/syndrome-util.lua | 7 +- .../devel/{printArgs.lua => print-args.lua} | 5 +- scripts/fix/{blooddel.lua => blood-del.lua} | 2 +- scripts/fix/{growthbug.lua => growth-bug.lua} | 30 ++- .../{forumdwarves.lua => forum-dwarves.lua} | 1 + scripts/{fullheal.lua => full-heal.lua} | 14 +- scripts/gui/{hackWish.lua => hack-wish.lua} | 3 +- scripts/modtools/create-item.lua | 10 +- scripts/modtools/force.lua | 2 + scripts/modtools/invader-item-destroyer.lua | 6 +- scripts/modtools/item-trigger.lua | 2 +- scripts/modtools/itemsyndrome.lua | 223 ------------------ scripts/modtools/moddableGods.lua | 153 ------------ scripts/modtools/projectile-trigger.lua | 1 + scripts/modtools/projectileExpansion.lua | 190 --------------- .../modtools/reaction-trigger-transition.lua | 2 +- scripts/modtools/reaction-trigger.lua | 2 +- scripts/modtools/shapechange.lua | 97 -------- scripts/modtools/skill-change.lua | 2 + scripts/modtools/skillroll.lua | 59 ----- scripts/modtools/spawn-flow.lua | 2 +- scripts/{removewear.lua => remove-wear.lua} | 11 +- 24 files changed, 76 insertions(+), 783 deletions(-) rename scripts/devel/{printArgs.lua => print-args.lua} (82%) rename scripts/fix/{blooddel.lua => blood-del.lua} (98%) rename scripts/fix/{growthbug.lua => growth-bug.lua} (50%) rename scripts/{forumdwarves.lua => forum-dwarves.lua} (99%) rename scripts/{fullheal.lua => full-heal.lua} (93%) rename scripts/gui/{hackWish.lua => hack-wish.lua} (99%) delete mode 100644 scripts/modtools/itemsyndrome.lua delete mode 100644 scripts/modtools/moddableGods.lua delete mode 100644 scripts/modtools/projectileExpansion.lua delete mode 100644 scripts/modtools/shapechange.lua delete mode 100644 scripts/modtools/skillroll.lua rename scripts/{removewear.lua => remove-wear.lua} (82%) diff --git a/NEWS b/NEWS index 4e9dd260e..1576ccf39 100644 --- a/NEWS +++ b/NEWS @@ -21,35 +21,29 @@ DFHack future syndrome-util.lua makes it easier to deal with unit syndromes scripts/ - forumdwarves.lua + forum-dwarves.lua helps copies df viewscreens to a file - fullheal.lua + full-heal.lua fully heals a unit - removewear.lua + remove-wear.lua removes wear from all items in the fort repeat.lua repeatedly calls a script or a plugin ShowUnitSyndromes.rb shows syndromes affecting units and other relevant info - skillChange.lua - changes the skill of a unit - Spawnunit.lua - creates units! - skillroll.lua - invokes dfhack commands based on random chances teleport.lua teleports units scripts/devel/ - printArgs.lua + print-args.lua scripts/fix/ - blooddel.lua + blood-del.lua makes it so civs don't bring barrels full of blood ichor or goo feeding-timers.lua reset the feeding timers of all units - growthbug.lua + growth-bug.lua fixes the growth bug scripts/gui/ - hackWish.lua + hack-wish.lua creates items out of any material unit-info-viewer.lua displays information about units @@ -60,18 +54,15 @@ DFHack future forces events: caravan, migrants, diplomat, megabeast, curiousbeast, mischievousbeast, flier, siege, nightcreature item-trigger.lua triggers commands based on equipping, unequipping, and wounding units with items - itemsyndrome.lua - adds and removes syndromes to units when they equip and unequip items interaction-trigger.lua triggers commands when interactions happen invader-item-destroyer.lua destroys invaders' items when they die moddable-gods.lua standardized version of Putnam's moddable gods script - moddableGods.lua - makes raw moddable gods possible - projectileExpansion.lua - adds extra functionality to projectiles + outside-only.lua + register buildings as outside only or inside only + replaces outsideOnly plugin projectile-trigger.lua standardized version of projectileExpansion reaction-trigger.lua @@ -97,10 +88,7 @@ DFHack future New plugins: Misc improvements: - new script in utils.lua for standardized argument processing - outside-only - now buildings have to be registered as inside or outside only, and it checks periodically to see when buildings change outsideness - converted from plugin to script + new function in utils.lua for standardized argument processing Removed digmat.rb: digFlood does the same functionality with less FPS impact diff --git a/library/lua/repeat-util.lua b/library/lua/repeat-util.lua index f4a1b701d..a7ccbefaa 100644 --- a/library/lua/repeat-util.lua +++ b/library/lua/repeat-util.lua @@ -1,5 +1,6 @@ -- lua/plugins/repeatUtil.lua -- author expwnent +-- tools for registering callbacks periodically -- vaguely based on a script by Putnam local _ENV = mkmodule("repeat-util") diff --git a/library/lua/syndrome-util.lua b/library/lua/syndrome-util.lua index 8fdf11a48..90e699de7 100644 --- a/library/lua/syndrome-util.lua +++ b/library/lua/syndrome-util.lua @@ -14,7 +14,7 @@ function findUnitSyndrome(unit,syn_id) return nil end ---usage: syndrome.ResetPolicy.DoNothing, syndrome.ResetPolicy.ResetDuration, etc +--usage: syndromeUtil.ResetPolicy.DoNothing, syndromeUtil.ResetPolicy.ResetDuration, etc ResetPolicy = ResetPolicy or utils.invert({ "DoNothing", "ResetDuration", @@ -37,7 +37,7 @@ function eraseSyndrome(unit,syndromeId,oldestFirst) end local syndromes = unit.syndromes.active for i=i1,iN,d do - if syndromes[i].type == syndromeId then + if syndromes[i]['type'] == syndromeId then syndromes:erase(i) return true end @@ -52,7 +52,8 @@ function eraseSyndromes(unit,syndromeId) end return count end ---target is a df.unit, syndrome is a df.syndrome, resetPolicy is one of syndrome.ResetPolicy + +--target is a df.unit, syndrome is a df.syndrome, resetPolicy is one of syndromeUtil.ResetPolicy --if the target has an instance of the syndrome already, the reset policy takes effect --returns true if the unit did not have the syndrome before calling and false otherwise function infectWithSyndrome(target,syndrome,resetPolicy) diff --git a/scripts/devel/printArgs.lua b/scripts/devel/print-args.lua similarity index 82% rename from scripts/devel/printArgs.lua rename to scripts/devel/print-args.lua index 095cd98b6..03c4bce0e 100644 --- a/scripts/devel/printArgs.lua +++ b/scripts/devel/print-args.lua @@ -1,9 +1,10 @@ ---printArgs.lua +--print-args.lua --author expwnent --prints all the arguments on their own line with quotes around them. useful for debugging local args = {...} -print("printArgs") +print("print-args") for _,arg in ipairs(args) do print("'"..arg.."'") end + diff --git a/scripts/fix/blooddel.lua b/scripts/fix/blood-del.lua similarity index 98% rename from scripts/fix/blooddel.lua rename to scripts/fix/blood-del.lua index aa1ea71a8..41b46dcb8 100644 --- a/scripts/fix/blooddel.lua +++ b/scripts/fix/blood-del.lua @@ -1,4 +1,4 @@ ---blooddel.lua +--blood-del.lua --makes it so that civs won't come with barrels full of blood, ichor, or goo --author Urist Da Vinci --edited by expwnent diff --git a/scripts/fix/growthbug.lua b/scripts/fix/growth-bug.lua similarity index 50% rename from scripts/fix/growthbug.lua rename to scripts/fix/growth-bug.lua index 368cfdc6a..27bddfa8e 100644 --- a/scripts/fix/growthbug.lua +++ b/scripts/fix/growth-bug.lua @@ -1,17 +1,25 @@ ---growthbug: units only grow when the current tick is 0 mod 10, so only 1/10 units will grow naturally. this script periodically sets the birth time of each unit so that it will grow ---to run periodically, use "repeat -time 2 months -command fix/growthBug now". see repeat.lua for details --- author expwnent +--growth-bug.lua: units only grow when the current tick is 0 mod 10, so only 1/10 units will grow naturally. this script periodically sets the birth time of each unit so that it will grow +--to run periodically, use "repeat -time 2 months -command fix/growth-bug -now". see repeat.lua for details +--author expwnent -local args = {...} -if args[1] ~= nil then - print("fix/growthbug usage") - print(" fix/growthbug") +local utils = require 'utils' + +validArgs = validArgs or utils.invert({ + 'help', + 'now' +}) + +local args = utils.processArgs({...}, validArgs) + +if args.help or not next(args) then + print("fix/growth-bug usage") + print(" fix/growth-bug") print(" fix the growth bug for all units on the map") - print(" fix/growthbug help") + print(" fix/growth-bug -help") print(" print this help message") - print(" repeat -time [n] [years/months/ticks/days/etc] -command fix/growthbug") + print(" repeat -time [n] [years/months/ticks/days/etc] -command fix/growth-bug now") print(" run this script every n time units") - print(" repeat -cancel fix/growthbug") + print(" repeat -cancel fix/growth-bug") print(" stop automatically running this script") end @@ -19,8 +27,8 @@ local count = 0 for _,unit in ipairs(df.global.world.units.all) do local offset = unit.relations.birth_time % 10; if offset ~= 0 then - count = count+1 unit.relations.birth_time = unit.relations.birth_time - offset + count = count+1 end end print("Fixed growth bug for "..count.." units.") diff --git a/scripts/forumdwarves.lua b/scripts/forum-dwarves.lua similarity index 99% rename from scripts/forumdwarves.lua rename to scripts/forum-dwarves.lua index 15ca9bd36..0b8828dfc 100644 --- a/scripts/forumdwarves.lua +++ b/scripts/forum-dwarves.lua @@ -1,3 +1,4 @@ +-- scripts/forum-dwarves.lua -- Save a copy of a text screen for the DF forums. Use 'forumdwarves help' for more details. -- original author: Caldfir -- edited by expwnent diff --git a/scripts/fullheal.lua b/scripts/full-heal.lua similarity index 93% rename from scripts/fullheal.lua rename to scripts/full-heal.lua index 01639c7db..64560890b 100644 --- a/scripts/fullheal.lua +++ b/scripts/full-heal.lua @@ -1,4 +1,4 @@ ---fullheal.lua +--full-heal.lua --author Kurik Amudnil, Urist DaVinci --edited by expwnent @@ -12,16 +12,16 @@ for _,arg in ipairs(args) do elseif tonumber(arg) then unit = df.unit.find(tonumber(arg)) elseif arg == 'help' or arg == '-help' or arg == '-h' then - print('fullheal: heal a unit completely from anything, optionally including death.') - print(' fullheal [unitId]') + print('full-heal: heal a unit completely from anything, optionally including death.') + print(' full-heal [unitId]') print(' heal the unit with the given id') - print(' fullheal -r [unitId]') + print(' full-heal -r [unitId]') print(' heal the unit with the given id and bring them back from death if they are dead') - print(' fullheal') + print(' full-heal') print(' heal the currently selected unit') - print(' fullheal -r') + print(' full-heal -r') print(' heal the currently selected unit and bring them back from death if they are dead') - print(' fullheal help') + print(' full-heal help') print(' print this help message') return end diff --git a/scripts/gui/hackWish.lua b/scripts/gui/hack-wish.lua similarity index 99% rename from scripts/gui/hackWish.lua rename to scripts/gui/hack-wish.lua index 26dcc86be..e1dc47696 100644 --- a/scripts/gui/hackWish.lua +++ b/scripts/gui/hack-wish.lua @@ -1,4 +1,4 @@ --- hackWish.lua +-- hack-wish.lua -- Allows for script-based wishing. -- author Putnam -- edited by expwnent @@ -249,3 +249,4 @@ else hackWish(unit) end end + diff --git a/scripts/modtools/create-item.lua b/scripts/modtools/create-item.lua index 5b9a7e973..d97e3d6de 100644 --- a/scripts/modtools/create-item.lua +++ b/scripts/modtools/create-item.lua @@ -4,13 +4,13 @@ local utils = require 'utils' -validArgs = --[[validArgs or]] utils.invert({ +validArgs = validArgs or utils.invert({ 'help', 'creator', 'material', 'item', - 'creature', - 'caste', +-- 'creature', +-- 'caste', 'matchingGloves', 'matchingShoes' }) @@ -38,6 +38,10 @@ arguments: specify the itemdef of the item to be created examples: WEAPON:ITEM_WEAPON_PICK + -matchingShoes + create two of this item + -matchingGloves + create two of this item, and set handedness appropriately ]]) return end diff --git a/scripts/modtools/force.lua b/scripts/modtools/force.lua index 4c0af1191..615b6b969 100644 --- a/scripts/modtools/force.lua +++ b/scripts/modtools/force.lua @@ -26,6 +26,8 @@ local args = utils.processArgs({...}, validArgs) if next(args) == nil or args.help then print([[force usage arguments: + -help + print this help message -eventType event specify the type of the event to trigger examples: diff --git a/scripts/modtools/invader-item-destroyer.lua b/scripts/modtools/invader-item-destroyer.lua index ce59bd516..2ec5eb582 100644 --- a/scripts/modtools/invader-item-destroyer.lua +++ b/scripts/modtools/invader-item-destroyer.lua @@ -90,7 +90,7 @@ end --TODO: delete corpses? end]] -validArgs = --[[validArgs or]] utils.invert({ +validArgs = validArgs or utils.invert({ 'clear', 'help', 'allRaces', @@ -113,6 +113,10 @@ end if args.help then print([[scripts/modtools/invader-item-destroyer.lua usage arguments: + -help + print this help message + -clear + reset all registered data -allEntities [true/false] set whether it should delete items from invaders from any civ -allItems [true/false] diff --git a/scripts/modtools/item-trigger.lua b/scripts/modtools/item-trigger.lua index 500457cc8..38ff70805 100644 --- a/scripts/modtools/item-trigger.lua +++ b/scripts/modtools/item-trigger.lua @@ -1,7 +1,7 @@ --scripts/modtools/attack-trigger.lua --author expwnent --based on itemsyndrome by Putnam ---triggers scripts when a unit attacks another with a weapon type, a weapon of a particular material +--triggers scripts when a unit attacks another with a weapon type, a weapon of a particular material, or a weapon contaminated with a particular material, or when a unit equips/unequips a particular item type, an item of a particular material, or an item contaminated with a particular material local eventful = require 'plugins.eventful' local utils = require 'utils' diff --git a/scripts/modtools/itemsyndrome.lua b/scripts/modtools/itemsyndrome.lua deleted file mode 100644 index 48256dcf5..000000000 --- a/scripts/modtools/itemsyndrome.lua +++ /dev/null @@ -1,223 +0,0 @@ --- itemsyndrome.lua --- author: Putnam --- edited by expwnent --- Checks for inventory changes and applies or removes syndromes that items or their materials have. Use "disable" (minus quotes) to disable and "help" to get help. - -eventful=eventful or require("plugins.eventful") -syndromeUtil = syndromeUtil or require("syndromeUtil") - -local function printItemSyndromeHelp() - print("Arguments (non case-sensitive):") - print(' "help": displays this dialogue.') - print(" ") - print(' "disable": disables the script.') - print(" ") - print(' "debugon/debugoff": debug mode.') - print(" ") - print(' "contaminantson/contaminantsoff": toggles searching for contaminants.') - print(' Disabling speeds itemsyndrome up greatly.') - print(' "transformReEquipOn/TransformReEquipOff": toggles transformation auto-reequip.') -end - -itemsyndromedebug=false - -local args = {...} -for k,v in ipairs(args) do - v=v:lower() - if v == "help" then printItemSyndromeHelp() return end - if v == "debugon" then itemsyndromedebug = true end - if v == "debugoff" then itemsyndromedebug = false end - if v == "contaminantson" then itemsyndromecontaminants = true end - if v == "contaminantsoff" then itemsyndromecontaminants = false end - if v == "transformreequipon" then transformationReEquip = true end - if v == "transformreequipoff" then transformationReEquip = false end -end - -local function getMaterial(item) - --What does this line mean? - local material = dfhack.matinfo.decode(item) and dfhack.matinfo.decode(item) or false - if not material then return nil end - if material.mode ~= "inorganic" then - return nil - else - return material.material --the "material" thing up there contains a bit more info which is all pretty important but impertinent, like the creature that the material comes from - end -end - -local function findItemSyndromeInorganic() - local allInorganics = {} - for matID,material in ipairs(df.global.world.raws.inorganics) do - if string.find(material.id,"DFHACK_ITEMSYNDROME_MATERIAL_") then table.insert(allInorganics,matID) end --the last underscore is needed to prevent duped raws; I want good modder courtesy if it kills me, dammit! - end - if itemsyndromedebug then printall(allInorganics) end - if #allInorganics>0 then return allInorganics else return nil end -end - -local function getAllItemSyndromeMats(itemSyndromeMatIDs) - local allActualInorganics = {} - for _,itemSyndromeMatID in ipairs(itemSyndromeMatIDs) do - table.insert(allActualInorganics,df.global.world.raws.inorganics[itemSyndromeMatID].material) - end - if itemsyndromedebug then printall(allActualInorganics) end - return allActualInorganics -end - -local function syndromeIsDfHackSyndrome(syndrome) - for k,v in ipairs(syndrome.syn_class) do - if v.value=="DFHACK_ITEM_SYNDROME" then - if itemsyndromedebug then print('Syndrome is DFHack syndrome, checking if creature is affected...') end - return true - end - end - if itemsyndromedebug then print('Syndrome is not DFHack syndrome. Cancelling.') end - return false -end - -local function itemHasNoSubtype(item) - return item:getSubtype()==-1 -end - -local function itemHasSyndrome(item) - if itemHasNoSubtype(item) or not itemSyndromeMats then return nil end - local allItemSyndromes={} - for _,material in ipairs(itemSyndromeMats) do - for __,syndrome in ipairs(material.syndrome) do - if syndrome.syn_name == item.subtype.name then table.insert(allItemSyndromes,syndrome) end - end - end - return #allItemSyndromes>0 and allItemSyndromes or false -end - -local function getValidPositions(syndrome) - local returnTable={AffectsHauler=false,AffectsStuckins=false,IsArmorOnly=false,IsWieldedOnly=false,OnlyAffectsStuckins=false} - for k,v in ipairs(syndrome.syn_class) do - if v.value:find('DFHACK') then - if v.value=="DFHACK_AFFECTS_HAULER" then returnTable.AffectsHauler=true end - if v.value=="DFHACK_AFFECTS_STUCKIN" then returnTable.AffectsStuckins=true end - if v.value=="DFHACK_STUCKINS_ONLY" then returnTable.OnlyAffectsStuckins=true end - if v.value=="DFHACK_WIELDED_ONLY" then returnTable.IsWieldedOnly=true end - if v.value=="DFHACK_ARMOR_ONLY" then returnTable.IsArmorOnly=true end - end - end - return returnTable -end - -local function itemIsInValidPosition(item_inv, syndrome) - local item = getValidPositions(syndrome) - if not item_inv then print("You shouldn't see this error! At all! Putnam f'd up! Tell him off!") return false end - local isInValidPosition=not ((item_inv.mode == 0 and not item.AffectsHauler) or (item_inv.mode == 7 and not item.AffectsStuckins) or (item_inv.mode ~= 2 and item.IsArmorOnly) or (item_inv.mode ~=1 and item.IsWieldedOnly) or (item_inv.mode ~=7 and item.OnlyAffectsStuckins)) - if itemsyndromedebug then print(isInValidPosition and 'Item is in correct position.' or 'Item is not in correct position.') end - return isInValidPosition -end - -local function syndromeIsTransformation(syndrome) - for _,effect in ipairs(syndrome.ce) do - if df.creature_interaction_effect_body_transformationst:is_instance(effect) then return true end - end - return false -end - -local function rememberInventory(unit) - local invCopy = {} - for inv_id,item_inv in ipairs(unit.inventory) do - invCopy[inv_id+1] = {} - local itemToWorkOn = invCopy[inv_id+1] - itemToWorkOn.item = item_inv.item - itemToWorkOn.mode = item_inv.mode - itemToWorkOn.body_part_id = item_inv.body_part_id - end - return invCopy -end - -local function moveAllToInventory(unit,invTable) - for _,item_inv in ipairs(invTable) do - dfhack.items.moveToInventory(item_inv.item,unit,item_inv.mode,item_inv.body_part_id) - end -end - -local function syndromeIsOnUnequip(syndrome) - for k,v in ipairs(syndrome.syn_class) do - if v.value:upper()=='DFHACK_ON_UNEQUIP' then return true end - end - return false -end - -local function addOrRemoveSyndromeDepending(unit,old_equip,new_equip,syndrome) - local item_inv=new_equip or old_equip - if not syndromeIsDfHackSyndrome(syndrome) then - return - end - local equippedOld = itemIsInValidPosition(old_equip,syndrome) - local equippedNew = itemIsInValidPosition(new_equip,syndrome) - if equippedOld == equippedNew then - return - end - local isOnEquip = not syndromeIsOnUnequip(syndrome) - local apply = (isOnEquip and equippedNew) or (not isOnEquip and not equippedNew) - if apply then - syndromeUtil.infectWithSyndrome(unit,syndrome,syndromeUtil.ResetPolicy.ResetDuration) - else - syndromeUtil.eraseSyndrome(unit,syndrome) - end -end - -eventful.enableEvent(eventful.eventType.INVENTORY_CHANGE,5) - -eventful.onInventoryChange.itemsyndrome=function(unit_id,item_id,old_equip,new_equip) - local item = df.item.find(item_id) - --if not item then return false end - if not item then - return - end - local unit = df.unit.find(unit_id) - if unit.flags1.dead then return false end - if itemsyndromedebug then print("Checking unit #" .. unit_id) end - local transformation = false - if itemsyndromedebug then print("checking item #" .. item_id .." on unit #" .. unit_id) end - local itemMaterial=getMaterial(item) - local function manageSyndromes(syndromes) - for k,syndrome in ipairs(syndromes) do - if itemsyndromedebug then print("item has a syndrome, checking if syndrome is valid for application...") end - if syndromeIsTransformation(syndrome) then - --unitInventory = rememberInventory(unit) - rememberInventory(unit) - transformation = true - end - addOrRemoveSyndromeDepending(unit,old_equip,new_equip,syndrome) - end - end - if itemMaterial then - manageSyndromes(itemMaterial.syndrome) - end - local itemSyndromes = itemHasSyndrome(item) - if itemSyndromes then - if itemsyndromedebug then print("Item itself has a syndrome, checking if item is in correct position and creature is affected") end - manageSyndromes(itemSyndromes) - end - if itemsyndromecontaminants and item.contaminants then - if itemsyndromedebug then print("Item has contaminants. Checking for syndromes...") end - for _,contaminant in ipairs(item.contaminants) do - local contaminantMaterial=getMaterial(contaminant) - if contaminantMaterial then - manageSyndromes(contaminantMaterial.syndrome) - end - end - end - if transformation and transformationReEquip then dfhack.timeout(2,"ticks",function() moveAllToInventory(unit,unitInventory) end) end -end - -dfhack.onStateChange.itemsyndrome=function(code) - if code==SC_WORLD_LOADED then - itemSyndromeMatIDs = findItemSyndromeInorganic() - if itemSyndromeMatIDs then itemSyndromeMats = getAllItemSyndromeMats(itemSyndromeMatIDs) end - end -end - -if disable then - eventful.onInventoryChange.itemsyndrome=nil - print("Disabled itemsyndrome.") - disable = false -else - print("Enabled itemsyndrome.") -end - diff --git a/scripts/modtools/moddableGods.lua b/scripts/modtools/moddableGods.lua deleted file mode 100644 index 2710b8bf0..000000000 --- a/scripts/modtools/moddableGods.lua +++ /dev/null @@ -1,153 +0,0 @@ --- moddableGods.lua --- Sets player-defined gods to correct civilizations. --- author: Putnam --- edited by expwnent - ---[[Here's an example of how to make a god: - -[CREATURE:SHEOGORATH] - [DOES_NOT_EXIST] - [MALE] - [NAME:jovial man:Daedra:madness] "Sheogorath, madness god." "Often depicted as a jovial man" - [CASTE_NAME:Sheogorath:Sheogorath:Sheogorath] - [DESCRIPTION:The Daedric Prince of madness.] - [CREATURE_CLASS:DFHACK_GOD] - [SPHERE:MUSIC] - [SPHERE:ART] - [SPHERE:CHAOS] -]] - -local function getCreatureClasses(creatureRaw) - local creatureClasses = {} - for _,caste in ipairs(creatureRaw.caste) do - for k,class in ipairs(caste.creature_class) do - table.insert(creatureClasses,class.value) - end - end - return creatureClasses -end - -local function deityIsOfSpecialCreature(creatureRaw) - for k,class in ipairs(getCreatureClasses(creatureRaw)) do - if class=="DFHACK_GOD" then return true end - end - return false -end - -local function scriptAlreadyRunOnThisWorld() - local figures = df.global.world.history.figures - for i=#figures-1,0,-1 do --goes through the table backwards because the particular hist figs involved are probably going to be the last - local figure = figures[i] - if not df.isnull(figure.flags) and figure.flags.deity and deityIsOfSpecialCreature(df.global.world.raws.creatures.all[figure.race]) then - return true - end - end - return false -end - -local function findAGod() - for k,fig in ipairs(df.global.world.history.figures) do - if fig.flags.deity then - return fig - end - end - return nil -end - -local function putListOfAllSpecialCreatureGodsTogether() - local specialCreatures = {} - for k,creatureRaw in ipairs(df.global.world.raws.creatures.all) do - if deityIsOfSpecialCreature(creatureRaw) then - table.insert(specialCreatures,{creatureRaw,k}) - end - end - return specialCreatures -end - -local function stringStarts(String,Start) - return string.sub(String,1,string.len(Start))==Start -end - -local function getRacesOfGod(god) - local civList={} - for k,class in ipairs(getCreatureClasses(god)) do - if stringStarts(class,"WORSHIP_ENTITY_") then - table.insert(civList,string.sub(class,15)) - end - end - return civList -end - -local function entityIsInGodsDomain(entity,entityRacesTable) - for k,v in ipairs(entityRacesTable) do - if v==entity.entity_raw.code then - return true - end - end - return false -end - -local function setUpTemplate(godFig,templateGod) - godFig.appeared_year=-1 - godFig.born_year=-1 - godFig.born_seconds=-1 - godFig.curse_year=-1 - godFig.curse_seconds=-1 - godFig.old_year=-1 - godFig.old_seconds=-1 - godFig.died_year=-1 - godFig.died_seconds=-1 - godFig.name.has_name=true - godFig.breed_id=-1 - godFig.flags:assign(templateGod.flags) - godFig.id = df.global.hist_figure_next_id - godFig.info = df.historical_figure_info:new() - godFig.info.spheres={new=true} - godFig.info.secret=df.historical_figure_info.T_secret:new() -end - -local function setUpGod(god,godID,templateGod) - local godFig = df.historical_figure:new() - setUpTemplate(godFig,templateGod) - godFig.sex=god.caste[0].gender - godFig.race=godID - godFig.name.first_name=god.caste[0].caste_name[2] --the adjectival form of the caste_name is used for the god's name, E.G, [CASTE_NAME:god:god:armok] - for k,v in ipairs(god.sphere) do --assigning spheres - godFig.info.spheres:insert('#',v) - end - df.global.world.history.figures:insert('#',godFig) - df.global.hist_figure_next_id=df.global.hist_figure_next_id+1 - return godFig -end - ---[[this function isn't really working right now so it's dummied out -function setGodAsOfficialDeityOfItsParticularEntity(god,godFig) - local entityRaces=getRacesOfGod(god) - for k,entity in ipairs(df.global.world.entities.all) do - if entityIsInGodsDomain(entity,entityRaces) then - entity.unknown1b.worship:insert('#',godFig.id) - end - end -end -]] -local function moddableGods() - if scriptAlreadyRunOnThisWorld() then - print("Already run on world...") - return false - end - local gods = putListOfAllSpecialCreatureGodsTogether() - local templateGod=findAGod() - for k,v in ipairs(gods) do --creature raws first - local god = v[1] - local godID = v[2] - local godFig = setUpGod(god,godID,templateGod) - --setGodAsOfficialDeityOfItsParticularEntity(god,godFig) - end -end - -dfhack.onStateChange.letThereBeModdableGods = function(state) - if state == SC_WORLD_LOADED and df.global.gamemode~=3 then --make sure that the gods show up only after the rest of the histfigs do - moddableGods() - end -end - diff --git a/scripts/modtools/projectile-trigger.lua b/scripts/modtools/projectile-trigger.lua index 5315a9fd2..e922d0018 100644 --- a/scripts/modtools/projectile-trigger.lua +++ b/scripts/modtools/projectile-trigger.lua @@ -1,6 +1,7 @@ --scripts/modtools/projectile-trigger.lua --author expwnent --based on Putnam's projectileExpansion +--TODO: trigger based on contaminants local eventful = require 'plugins.eventful' local utils = require 'utils' diff --git a/scripts/modtools/projectileExpansion.lua b/scripts/modtools/projectileExpansion.lua deleted file mode 100644 index df691fc77..000000000 --- a/scripts/modtools/projectileExpansion.lua +++ /dev/null @@ -1,190 +0,0 @@ --- projectileExpansion.lua --- author: Putnam --- edited by expwnent --- Adds extra functionality to projectiles. Use the argument "disable" (minus quotes) to disable. - -local syndromeUtil = require("syndromeUtil") -local events=require "plugins.eventful" - -local flowtypes = { - miasma = 0, - mist = 1, - mist2 = 2, - dust = 3, - lavaMist = 4, - smoke = 5, - dragonFire = 6, - fireBreath = 7, - web = 8, - undirectedGas = 9, - undirectedVapor = 10, - oceanWave = 11, - seaFoam = 12 -} - -local function posIsEqual(pos1,pos2) - if pos1.x ~= pos2.x or pos1.y ~= pos2.y or pos1.z ~= pos2.z then return false end - return true -end - -local function getMaterial(item) - if not dfhack.matinfo.decode(item) then return nil end - local matinfo = dfhack.matinfo.decode(item) - return matinfo and matinfo.material --- return dfhack.matinfo.decode(item).material -end - -local function getSyndrome(material) - if material==nil then return nil end - if #material.syndrome>0 then return material.syndrome[0] - else return nil end -end - -local function removeItem(item) - item.flags.garbage_collect = true -end - -local function findInorganicWithName(matString) - for inorganicID,material in ipairs(df.global.world.raws.inorganics) do - if material.id == matString then return inorganicID end - end - return nil -end - -local function getScriptFromMaterial(material) - local commandStart - local commandEnd - local reactionClasses = material.reaction_class - for classNumber,reactionClass in ipairs(reactionClasses) do - if reactionClass.value == "\\COMMAND" then commandStart = classNumber end - if reactionClass.value == "\\ENDCOMMAND" then commandEnd = classNumber break end - end - local script = {} - if commandStart and commandEnd then - for i = commandStart+1, commandEnd-1, 1 do - table.insert(script,reactionClasses[i].value) - end - end - return script -end - -local function getUnitHitByProjectile(projectile) - for uid,unit in ipairs(df.global.world.units.active) do - if posIsEqual(unit.pos,projectile.cur_pos) then return uid,unit end - end - return nil -end - -local function matCausesSyndrome(material) - for _,reactionClass in ipairs(material.reaction_class) do - if reactionClass.value == "DFHACK_CAUSES_SYNDROME" then return true end --the syndrome is the syndrome local to the projectile material - end - return false -end - -projectileExpansionFlags = projectilExpansionFlags or { - matWantsSpecificInorganic = 0, - matWantsSpecificSize = 50000, - matCausesDragonFire = false, - matCausesMiasma = false, - matCausesMist = false, - matCausesMist2 = false, - matCausesDust = false, - matCausesLavaMist = false, - matCausesSmoke = false, - matCausesFireBreath = false, - matCausesWeb = false, - matCausesUndirectedGas = false, - matCausesUndirectedVapor = false, - matCausesOceanWave = false, - matCausesSeaFoam = false, - matHasScriptAttached = false, - matCausesSyndrome = false, - returnLocation = false, - matDisappearsOnHit = false -} - -local function getProjectileExpansionFlags(material) - local matName = nil - for k,reactionClass in ipairs(material.reaction_class) do - if debugProjExp then print("checking reaction class #" .. k .. "...",reactionClass.value) end - if string.find(reactionClass.value,"DFHACK") then - if debugProjExp then print("DFHack reaction class found!") end - if reactionClass.value == "DFHACK_SPECIFIC_MAT" then matName = material.reaction_class[k+1].value end - if reactionClass.value == "DFHACK_FLOW_SIZE" then projectileExpansionFlags.matWantsSpecificSize = tonumber(material.reaction_class[k+1].value) end - if reactionClass.value == "DFHACK_CAUSES_SYNDROME" then projectileExpansionFlags.matCausesSyndrome = true end - if reactionClass.value == "DFHACK_DRAGONFIRE" then projectileExpansionFlags.matCausesDragonFire = true end - if reactionClass.value == "DFHACK_MIASMA" then projectileExpansionFlags.matCausesMiasma = true end - if reactionClass.value == "DFHACK_MIST" then projectileExpansionFlags.matCausesMist = true end - if reactionClass.value == "DFHACK_MIST2" then projectileExpansionFlags.matCausesMist2 = true end - if reactionClass.value == "DFHACK_DUST" then projectileExpansionFlags.matCausesDust = true end - if reactionClass.value == "DFHACK_LAVAMIST" then projectileExpansionFlags.matCausesLavaMist = true end - if reactionClass.value == "DFHACK_SMOKE" then projectileExpansionFlags.matCausesSmoke = true end - if reactionClass.value == "DFHACK_FIREBREATH" then projectileExpansionFlags.matCausesFireBreath = true end - if reactionClass.value == "DFHACK_WEB" then projectileExpansionFlags.matCausesWeb = true end - if reactionClass.value == "DFHACK_GAS_UNDIRECTED" then projectileExpansionFlags.matCausesUndirectedGas = true end - if reactionClass.value == "DFHACK_VAPOR_UNDIRECTED" then projectileExpansionFlags.matCausesUndirectedVapor = true end - if reactionClass.value == "DFHACK_OCEAN_WAVE" then projectileExpansionFlags.matCausesOceanWave = true end - if reactionClass.value == "DFHACK_SEA_FOAM" then projectileExpansionFlags.matCausesSeaFoam = true end - if reactionClass.value == "DFHACK_DISAPPEARS" then projectileExpansionFlags.matDisappearsOnHit = true end - end - if reactionClass.value == "\\COMMAND" then projectileExpansionFlags.matHasScriptAttached = true end - end - if matName then projectileExpansionFlags.matWantsSpecificInorganic = findInorganicWithName(matName) end - return projectileExpansionFlags -end - -debugProjExp=false - -events.onProjItemCheckImpact.expansion=function(projectile) - if debugProjExp then print("Thwack! Projectile item hit. Running projectileExpansion.") end - if projectile then - if debugProjExp then print("Found the item. Working on it.") end - local material = getMaterial(projectile.item) - if not material then return nil end - local projectileExpansionFlags=getProjectileExpansionFlags(material) - if debugProjExp then print(projectileExpansionFlags) printall(projectileExpansionFlags) end - local syndrome = getSyndrome(material) - local emissionMat = projectileExpansionFlags.matWantsSpecificInorganic --defaults to iron - local flowSize = projectileExpansionFlags.matWantsSpecificSize --defaults to 50000 - if projectileExpansionFlags.matCausesDragonFire then dfhack.maps.spawnFlow(projectile.cur_pos,flowtypes.dragonFire,0,0,flowSize) end - if projectileExpansionFlags.matCausesMiasma then dfhack.maps.spawnFlow(projectile.cur_pos,flowtypes.miasma,0,0,flowSize) end - if projectileExpansionFlags.matCausesMist then dfhack.maps.spawnFlow(projectile.cur_pos,flowtypes.mist,0,0,flowSize) end - if projectileExpansionFlags.matCausesMist2 then dfhack.maps.spawnFlow(projectile.cur_pos,flowtypes.mist2,0,0,flowSize) end - if projectileExpansionFlags.matCausesDust then dfhack.maps.spawnFlow(projectile.cur_pos,flowtypes.dust,0,emissionMat,flowSize) end - if projectileExpansionFlags.matCausesLavaMist then dfhack.maps.spawnFlow(projectile.cur_pos,flowtypes.lavaMist,0,emissionMat,flowSize) end - if projectileExpansionFlags.matCausesSmoke then dfhack.maps.spawnFlow(projectile.cur_pos,flowtypes.smoke,0,0,flowSize) end - if projectileExpansionFlags.matCausesFireBreath then dfhack.maps.spawnFlow(projectile.cur_pos,flowtypes.fireBreath,0,0,flowSize) end - if projectileExpansionFlags.matCausesWeb then dfhack.maps.spawnFlow(projectile.cur_pos,flowtypes.web,0,emissionMat,flowSize) end - if projectileExpansionFlags.matCausesUndirectedGas then dfhack.maps.spawnFlow(projectile.cur_pos,flowtypes.undirectedGas,0,emissionMat,flowSize) end - if projectileExpansionFlags.matCausesUndirectedVapor then dfhack.maps.spawnFlow(projectile.cur_pos,flowtypes.undirectedVapor,0,emissionMat,flowSize) end - if projectileExpansionFlags.matCausesOceanWave then dfhack.maps.spawnFlow(projectile.cur_pos,flowtypes.oceanWave,0,0,flowSize) end - if projectileExpansionFlags.matCausesSeaFoam then dfhack.maps.spawnFlow(projectile.cur_pos,flowtypes.seaFoam,0,0,flowSize) end - if projectileExpansionFlags.matHasScriptAttached or projectileExpansionFlags.matCausesSyndrome then - local uid,unit = getUnitHitByProjectile(projectile) - if projectileExpansionFlags.matHasScriptAttached then - local script = getScriptFromMaterial(material) - for k,v in ipairs(script) do - if script[k] == "\\UNIT_HIT_ID" then script[k] = unit.id end - if script[k] == "\\LOCATION" then - script[k] = projectile.cur_pos.x - table.insert(script,projectile.cur_pos.y,k+1) - table.insert(script,projectile.cur_pos.z,k+2) - end - end - dfhack.run_script(table.unpack(script)) - end - if projectileExpansionFlags.matCausesSyndrome then syndromeUtil.infectWithSyndrome(unit,syndrome.id) end - end - --if projectileExpansionFlags.matDisappearsOnHit then dfhack.items.remove(projectile) end - end - return true -end - -if ... ~= "disable" then - print("Enabled projectileExpansion.") -else - events.onProjItemCheckImpact.expansion = nil - print("Disabled projectileExpansion.") -end - diff --git a/scripts/modtools/reaction-trigger-transition.lua b/scripts/modtools/reaction-trigger-transition.lua index 7193d2d0c..8e5f7f15e 100644 --- a/scripts/modtools/reaction-trigger-transition.lua +++ b/scripts/modtools/reaction-trigger-transition.lua @@ -1,4 +1,4 @@ --- reaction-trigger-transition.lua +-- scripts/modtools/reaction-trigger-transition.lua -- author expwnent -- prints useful things to the console and a file to help modders transition from autoSyndrome to reaction-trigger -- this script is basically an apology for breaking backward compatibiility diff --git a/scripts/modtools/reaction-trigger.lua b/scripts/modtools/reaction-trigger.lua index e878aef06..fdc6b745b 100644 --- a/scripts/modtools/reaction-trigger.lua +++ b/scripts/modtools/reaction-trigger.lua @@ -148,7 +148,7 @@ eventful.onJobCompleted.reactionTrigger = function(job) end eventful.enableEvent(eventful.eventType.JOB_COMPLETED,0) --0 is necessary to catch cancelled jobs and not trigger them -validArgs = utils.invert({ +validArgs = validArgs or utils.invert({ 'help', 'clear', 'reactionName', diff --git a/scripts/modtools/shapechange.lua b/scripts/modtools/shapechange.lua deleted file mode 100644 index e46129e81..000000000 --- a/scripts/modtools/shapechange.lua +++ /dev/null @@ -1,97 +0,0 @@ --- shapechange.lua --- transforms unit (by number) into another creature, choice given to user. Syntax is: unitID tickamount maxsize namefilter. A size of 0 is ignored. A length of 0 is also ignored. If no filter, all units will be sorted. A filter of ALL will also work with all units. --- author Putnam --- edited by expwnent - ---shapechange gui [unitId] [duration] [maxsize] [namefilter] ---shapechange manual [unitId] [creature name] [caste name] [duration] - -local dialog = require('gui.dialogs') -local script = require('gui.script') -function transform(target,race,caste,length) - if target==nil then - qerror("Not a valid target") - end - local defaultRace = target.enemy.normal_race - local defaultCaste = target.enemy.normal_caste - target.enemy.normal_race = race --that's it??? - target.enemy.normal_caste = caste; --that's it! - if length and length>0 then dfhack.timeout(length,'ticks',function() target.enemy.normal_race = defaultRace target.enemy.normal_caste = defaultCaste end) end -end - -function getBodySize(caste) - return caste.body_size_1[#caste.body_size_1-1] -end - -function selectCreature(unitID,length,size,filter) --taken straight from here, but edited so I can understand it better: https://gist.github.com/warmist/4061959/... again. Also edited for syndromeTrigger, but in a completely different way. - size = size or 0 - filter = filter or "all" - length = length or 2400 - local creatures=df.global.world.raws.creatures.all - local tbl={} - local tunit=df.unit.find(unitID) - for cr_k,creature in ipairs(creatures) do - for ca_k,caste in ipairs(creature.caste) do - local name=caste.caste_name[0] - if name=="" then name="?" end - if (not filter or string.find(name,filter) or string.lower(filter)=="all") and (not size or size>getBodySize(caste) or size<1 and not creature.flags.DOES_NOT_EXIST) then table.insert(tbl,{name,nil,cr_k,ca_k}) end - end - end - table.sort(tbl,function(a,b) return a[1]1 and size or "infinity") - .. " (" - .. size/(getBodySize(df.creature_raw.find(tunit.race).caste[tunit.caste]))*100 - .. "% of current size) for " - ..length - .." ticks (" - ..length/1200 - .." days, ~" - ..length/df.global.enabler.fps - .." seconds)?", - COLOR_LIGHTRED - ) - if ok then dialog.showListPrompt("Creature Selection","Choose creature:",COLOR_WHITE,tbl,f) end - end) -end - -local args = {...} ---unit id, length, size, filter -if args[1] == 'gui' then - selectCreature(tonumber(args[2]),tonumber(args[3]),tonumber(args[4]),args[5]) -else - local race-- = df.creature_raw.find(args[3]) - local raceIndex - for index,raceCandidate in ipairs(df.global.world.raws.creatures.all) do - if raceCandidate.creature_id == args[3] then - raceIndex = index - race = raceCandidate - break - end - end - local caste - local casteIndex - if race then - for index,casteCandidate in ipairs(race.caste) do - if casteCandidate.caste_id == args[4] then - caste = casteCandidate - casteIndex = index - break - end - end - end - if not race or not caste then - print("shapechange error: couldn't find " .. args[3] .. " " .. args[4]) - return - end - transform(df.unit.find(tonumber(args[2])), raceIndex, casteIndex, args[5] and tonumber(args[5])) -end - diff --git a/scripts/modtools/skill-change.lua b/scripts/modtools/skill-change.lua index bddb58617..98be8341c 100644 --- a/scripts/modtools/skill-change.lua +++ b/scripts/modtools/skill-change.lua @@ -1,6 +1,8 @@ --scripts/modtools/skill-change.lua --author expwnent --based on skillChange.lua by Putnam +--TODO: update skill level once experience increases/decreases +--TODO: skill rust? local utils = require 'utils' diff --git a/scripts/modtools/skillroll.lua b/scripts/modtools/skillroll.lua deleted file mode 100644 index e3a73f510..000000000 --- a/scripts/modtools/skillroll.lua +++ /dev/null @@ -1,59 +0,0 @@ --- skillroll.lua --- Allows skills to activate lua scripts. --- author Putnam --- edited by expwnent - ---[[Example usage: -...syndrome stuff... -[SYN_CLASS:\COMMAND][SYN_CLASS:modtools/skillroll][SYN_CLASS:\WORKER_ID] For autoSyndrome/syndromeTrigger. -[SYN_CLASS:MELEE_COMBAT] Can use any skill, including NONE (no bonus) -[SYN_CLASS:20] Rolls uniformly from 1 to 20 inclusive. Skill will be weighted to this value. -[SYN_CLASS:DICEROLL_1] If diceroll ends up as one... -[SYN_CLASS:kill][SYN_CLASS:\SKILL_UNIT_ID] Theoretical kill-given-unit-id command; slayrace doesn't do so. -[SYN_CLASS:DICEROLL_10] If diceroll is between 1 and 10 (2-10, inclusive)... -[SYN_CLASS:modtools/force][SYN_CLASS:migrants][SYN_CLASS:player] Force migrants. -[SYN_CLASS:DICEROLL_19] If diceroll is between 10 and 19 (11-19, inclusive)... -[SYN_CLASS:fullheal][SYN_CLASS:\SKILL_UNIT_ID] Fully heals unit. -[SYN_CLASS:DICEROLL_20] If diceroll is at least 20... -[SYN_CLASS:modtools/shapechange][SYN_CLASS:\SKILL_UNIT_ID] Turns unit into any creature permanently. - -or from the console -modtools/skillroll workerId MELEE_COMBAT 20 DICEROLL_1 kill workerId DICEROLL_10 modtools/force migrants player DICEROLL_19 fullheal workerId DICEROLL_20 modtools/shapechange workerId -]] - -local args={...} -if args[1]=='dryrun' then - unit=df.global.world.units.all[0] -end -local unit = unit or df.unit.find(args[1]) -rando=rando or dfhack.random.new() -local roll=rando:random(tonumber(args[3])) -if args[2] ~= 'NONE' then - local result=roll+(dfhack.units.getEffectiveSkill(unit,df.job_skill[args[2]])*(tonumber(args[3])/20)) - result = result%1<.5 and math.floor(result) or math.ceil(result) - roll = result -end - -local i=4 -local command={} -local scriptIsFinished -repeat - local arg=args[i] - if arg:find('DICEROLL') then - local dicerollnumber=tonumber(arg:match('%d+')) --yes this is truly naive as hell; I imagine if you put DICEROLL3%moa5oam3 it'll return 353. - if dicerollnumber>=roll then - repeat - i=i+1 - if i<=#args and (not args[i]:find('DICEROLL')) then - if args[i]~='\\SKILL_UNIT_ID' then table.insert(command,args[i]) else table.insert(command,args[1]) end - end - until i>#args or args[i]:find('DICEROLL') - dfhack.run_command(table.unpack(command)) - scriptIsFinished=true - else - i=i+1 - end - else - i=i+1 - end -until i>#args or scriptIsFinished diff --git a/scripts/modtools/spawn-flow.lua b/scripts/modtools/spawn-flow.lua index 3dd615bff..3e6445120 100644 --- a/scripts/modtools/spawn-flow.lua +++ b/scripts/modtools/spawn-flow.lua @@ -4,7 +4,7 @@ local utils = require 'utils' -validArgs = --[[validArgs or]] utils.invert({ +validArgs = validArgs or utils.invert({ 'help', 'material', 'flowType', diff --git a/scripts/removewear.lua b/scripts/remove-wear.lua similarity index 82% rename from scripts/removewear.lua rename to scripts/remove-wear.lua index 66d427e48..56fe42edc 100644 --- a/scripts/removewear.lua +++ b/scripts/remove-wear.lua @@ -1,3 +1,4 @@ +-- scripts/remove-wear.lua -- Resets all items in your fort to 0 wear -- original author: Laggy -- edited by expwnent @@ -5,13 +6,13 @@ local args = {...} if args[1] == 'help' then - print([[removewear - this script removes wear from all items, or from individual ones + print([[remove-wear - this script removes wear from all items, or from individual ones -removewear all +remove-wear all remove wear from all items -removewear n1 n2 n3 ... +remove-wear n1 n2 n3 ... remove wear from items with the given ids. order does not matter -repeat -time 2 months -command removewear all +repeat -time 2 months -command remove-wear all remove wear from all items every 2 months. see repeat.lua for details ]]) do return end @@ -23,7 +24,7 @@ elseif args[1] == 'all' then count = count+1 end end - print('removewear removed wear from '..count..' objects') + print('remove-wear removed wear from '..count..' objects') else local argIndex = 1 local isCompleted = {}