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