Lots of tweaks.
							parent
							
								
									1ce38f3e3a
								
							
						
					
					
						commit
						a8f810cc3b
					
				| @ -1,9 +1,10 @@ | |||||||
| --printArgs.lua | --print-args.lua | ||||||
| --author expwnent | --author expwnent | ||||||
| --prints all the arguments on their own line with quotes around them. useful for debugging | --prints all the arguments on their own line with quotes around them. useful for debugging | ||||||
| 
 | 
 | ||||||
| local args = {...} | local args = {...} | ||||||
| print("printArgs") | print("print-args") | ||||||
| for _,arg in ipairs(args) do | for _,arg in ipairs(args) do | ||||||
|  print("'"..arg.."'") |  print("'"..arg.."'") | ||||||
| end | end | ||||||
|  | 
 | ||||||
| @ -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 | --makes it so that civs won't come with barrels full of blood, ichor, or goo | ||||||
| --author Urist Da Vinci | --author Urist Da Vinci | ||||||
| --edited by expwnent | --edited by expwnent | ||||||
| @ -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. | -- Save a copy of a text screen for the DF forums.  Use 'forumdwarves help' for more details. | ||||||
| -- original author: Caldfir | -- original author: Caldfir | ||||||
| -- edited by expwnent | -- edited by expwnent | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
| @ -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]<b[1] end) |  | ||||||
|  local f=function(name,C) |  | ||||||
|   transform(tunit,C[3],C[4],length) |  | ||||||
|  end |  | ||||||
|  script.start(function() |  | ||||||
|   local ok =  |  | ||||||
|    script.showYesNoPrompt( |  | ||||||
|     "Just checking","Do you want "  |  | ||||||
|     .. dfhack.TranslateName(dfhack.units.getVisibleName(tunit)) |  | ||||||
| 	.. " to transform into a creature of size below "..NEWLINE |  | ||||||
|     .. (not not size and size>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 |  | ||||||
| 
 |  | ||||||
| @ -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 |  | ||||||
		Loading…
	
		Reference in New Issue