Added reaction-trigger.lua to replace autoSyndrome.

develop
expwnent 2014-06-29 06:12:54 -04:00
parent a54ad7e5a0
commit ed90ccf5ea
2 changed files with 348 additions and 0 deletions

@ -0,0 +1,137 @@
-- 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
local function maybeQuote(str)
if str == '' or string.find(str,' ') then
return ('"' .. str .. '"')
else
return str
end
end
warnings = ''
output = ''
for _,reaction in ipairs(df.global.world.raws.reactions) do
local function foreachProduct(product)
local prodType = product:getType()
if prodType ~= df.reaction_product_type.item then
return
end
if product.item_type ~= df.item_type.BOULDER then
return
end
if product.mat_index < 0 then
return
end
local inorganic = df.global.world.raws.inorganics[product.mat_index]
local didInorganicName
for _,syndrome in ipairs(inorganic.material.syndrome) do
local workerOnly = true
local allowMultipleTargets = false;
local command
local commandStr
local destroyRock = true;
local foundAutoSyndrome = false;
local resetPolicy;
for i,synclass in ipairs(syndrome.syn_class) do
synclass = synclass.value
if false then
elseif synclass == '\\AUTO_SYNDROME' then
foundAutoSyndrome = true
elseif synclass == '\\ALLOW_NONWORKER_TARGETS' then
workerOnly = false
elseif synclass == '\\ALLOW_MULTIPLE_TARGETS' then
allowMultipleTargets = true
elseif synclass == '\\PRESERVE_ROCK' then
destroyRock = false
elseif synclass == '\\RESET_POLICY DoNothing' then
resetPolicy = 'DoNothing'
elseif synclass == '\\RESET_POLICY ResetDuration' then
resetPolicy = 'ResetDuration'
elseif synclass == '\\RESET_POLICY AddDuration' then
resetPolicy = 'AddDuration'
elseif synclass == '\\RESET_POLICY NewInstance' then
resetPolicy = 'NewInstance'
elseif synclass == '\\COMMAND' then
command = ''
elseif command then
if synclass == '\\LOCATION' then
command = command .. '\\LOCATION '
elseif synclass == '\\WORKER_ID' then
command = command .. '\\WORKER_ID '
elseif synclass == '\\REACTION_INDEX' then
warnings = warnings .. ('Warning: \\REACTION_INDEX is deprecated. Use \\REACTION_NAME instead.\n')
command = command .. '\\REACTION_NAME '
else
commandStr = true
command = command .. maybeQuote(synclass) .. ' '
end
end
end
if foundAutoSyndrome then
if destroyRock then
warnings = warnings .. ('Warning: instead of destroying the rock, do not produce it in the first place.\n')
end
if workerOnly then
workerOnly = 'true'
else
workerOnly = 'false'
end
if allowMultipleTargets then
allowMultipleTargets = 'true'
else
allowMultipleTargets = 'false'
end
local reactionTriggerStr = 'modtools/reaction-trigger -reactionName ' .. maybeQuote(reaction.code) --.. '"'
if workerOnly ~= 'true' then
reactionTriggerStr = reactionTriggerStr .. ' -workerOnly ' .. workerOnly
end
if allowMultipleTargets ~= 'false' then
reactionTriggerStr = reactionTriggerStr .. ' -allowMultipleTargets ' .. allowMultipleTargets
end
if resetPolicy and resetPolicy ~= 'NewInstance' then
reactionTriggerStr = reactionTriggerStr .. ' -resetPolicy ' .. resetPolicy
end
if #syndrome.ce > 0 then
if syndrome.syn_name == '' then
warnings = warnings .. ('Warning: give this syndrome a name!\n')
end
reactionTriggerStr = reactionTriggerStr .. ' -syndrome ' .. maybeQuote(syndrome.syn_name) .. ''
end
if command and commandStr then
reactionTriggerStr = reactionTriggerStr .. ' -command ' .. command
end
if (not command or command == '') and (not syndrome.syn_name or syndrome.syn_name == '') then
--output = output .. '#'
else
if not didInorganicName then
-- output = output .. '# ' .. (inorganic.id) .. '\n'
didInorganicName = true
end
output = output .. (reactionTriggerStr) .. '\n'
end
end
end
end
for _,product in ipairs(reaction.products) do
foreachProduct(product)
end
end
print(warnings)
print('\n\n\n\n')
print(output)
local file = io.open('reaction-trigger-transition.txt', 'w+')
--io.output(file)
--file:write(warnings)
--file:write('\n\n\n\n')
file:write(output)
file:flush()
--io.flush(file)
io.close(file)
--io.output()
print('transition information written to reaction-trigger-transition.txt')

@ -0,0 +1,211 @@
-- reaction-trigger.lua
-- author expwnent
-- replaces autoSyndrome: trigger commands when custom reactions are completed
local eventful = require 'plugins.eventful'
local syndromeUtil = require 'syndromeUtil'
reactionHooks = reactionHooks or {}
local function getWorkerAndBuilding(job)
local workerId = -1
local buildingId = -1
for _,generalRef in ipairs(job.general_refs) do
if generalRef:getType() == df.general_ref_type.UNIT_WORKER then
if workerId ~= -1 then
print(job)
printall(job)
error('reaction-trigger: two workers on same job: ' .. workerId .. ', ' .. generalRef.unit_id)
else
workerId = generalRef.unit_id
if workerId == -1 then
print(job)
printall(job)
error('reaction-trigger: invalid worker')
end
end
elseif generalRef:getType() == df.general_ref_type.BUILDING_HOLDER then
if buildingId ~= -1 then
print(job)
printall(job)
error('reaction-trigger: two buildings same job: ' .. buildingId .. ', ' .. generalRef.building_id)
else
buildingId = generalRef.building_id
if buildingId == -1 then
print(job)
printall(job)
error('reaction-trigger: invalid building')
end
end
end
end
return workerId,buildingId
end
local function processCommand(job, worker, target, building, command)
local result = {}
for _,arg in ipairs(command) do
if arg == '\\WORKER_ID' then
table.insert(result,''..worker.id)
elseif arg == '\\TARGET_ID' then
table.insert(restul,''..target.id)
elseif arg == '\\BUILDING_ID' then
table.insert(result,''..building.id)
elseif arg == '\\LOCATION' then
table.insert(result,''..job.pos.x)
table.insert(result,''..job.pos.y)
table.insert(result,''..job.pos.z)
elseif arg == '\\REACTION_NAME' then
table.insert(result,''..job.reaction_name)
else
table.insert(result,arg)
end
end
return result
end
eventful.onJobCompleted.reactionTrigger = function(job)
if job.completion_timer > 0 then
return
end
-- if job.job_type ~= df.job_type.CustomReaction then
-- --TODO: support builtin reaction triggers if someone asks
-- return
-- end
if not job.reaction_name or job.reaction_name == '' then
return
end
-- print('reaction name: ' .. job.reaction_name)
if not job.reaction_name or not reactionHooks[job.reaction_name] then
return
end
local worker,building = getWorkerAndBuilding(job)
worker = df.unit.find(worker)
building = df.building.find(building)
if not worker or not building then
--this probably means that it finished before EventManager could get a copy of the job while the job was running
--TODO: consider printing a warning once
return
end
local function doAction(action)
local didSomething
if action.args then
local processed = processCommand(job, worker, worker, building, action.args)
print(dfhack.run_command(table.unpack(processed)))
end
if action.syndrome then
didSomething = syndromeUtil.infectWithSyndromeIfValidTarget(worker, action.syndrome, action.resetPolicy) or didSomething
end
if action.workerOnly then
return
end
if didSomething and not action.allowMultipleTargets then
return
end
local function foreach(unit)
if unit == worker then
return false
elseif unit.pos.z ~= building.z then
return false
elseif unit.pos.x < building.x1 or unit.pos.x > building.x2 then
return false
elseif unit.pos.y < building.y1 or unit.pos.y > building.y2 then
return false
else
if action.args then
processCommand(job, worker, unit, building, action.args)
end
if action.syndrome then
didSomething = syndrome.infectWithSyndromeIfValidTarget(unit,action.syndrome,action.resetPolicy) or didSomething
end
if didSomething and not action.allowMultipleTargets then
return true
end
return false
end
end
for _,unit in ipairs(df.global.world.units.all) do
if foreach(unit) then
break
end
end
end
for _,action in ipairs(reactionHooks[job.reaction_name]) do
doAction(action)
end
end
eventful.enableEvent(eventful.eventType.JOB_COMPLETED,0)
local args = {...}
local i=1
local reactionName
local action = {}
action.workerOnly = true
action.allowMultipleTargets = false
--action.args = {}
--action.syndrome, action.resetPolicy, action.workerOnly, action.allowMultipleTargets, action.args
while i <= #args do
if action.args then
table.insert(action.args, args[i])
i = i+1
else
if args[i] == '-clear' then
reactionHooks = {}
i = i+1
elseif args[i] == '-reactionName' then
reactionName = args[i+1]
i = i+2
elseif args[i] == '-syndrome' then
if action.syndrome then
error('only one syndrome at a time permitted')
end
for _,syndrome in ipairs(df.global.world.raws.syndromes.all) do
if syndrome.syn_name == args[i+1] then
action.syndrome = syndrome
break
end
end
if not action.syndrome then
error('could not find syndrome ' .. args[i+1])
end
i = i+2
elseif args[i] == '-workerOnly' then
action.workerOnly = args[i+1] == 'true'
i = i+2
elseif args[i] == '-allowMultipleTargets' then
action.allowMultipleTargets = args[i+1] == 'true'
i = i+2
elseif args[i] == '-command' then
action.args = {}
i = i+1
elseif args[i] == '-resetPolicy' then
action.resetPolicy = syndromeUtil.ResetPolicy[args[i+1]]
if not action.resetPolicy then
error('invalid reset policy: ' .. args[i+1])
end
i = i+2
else
error('invalid arguments')
end
end
end
if not reactionName then
return
end
if action.args then
print(action.args)
printall(action.args)
end
if not reactionHooks[reactionName] then
reactionHooks[reactionName] = {}
end
table.insert(reactionHooks[reactionName], action)