Skip to content

Commit

Permalink
Added many forum scripts, and a makeshift onReport/onStrike event tha…
Browse files Browse the repository at this point in the history
…t will be merged into eventful/EventManager later.
  • Loading branch information
expwnent committed Jun 26, 2014
1 parent f5de76e commit 596ab0e
Show file tree
Hide file tree
Showing 26 changed files with 4,259 additions and 0 deletions.
74 changes: 74 additions & 0 deletions plugins/lua/onReport.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
--onReport.lua
--author expwnent
--contains the "ON_REPORT" event: triggered when there is a new report in df.global.world.status.reports

--example
--local onReport = require 'plugins.onReport'
--onReport.triggers.someName = function (reportId)
-- --do stuff with that id
--end

local _ENV = mkmodule('onReport')
local utils = require 'utils'
local repeatUtil = require 'plugins.repeatUtil'

lastReport = lastReport or -1
triggers = triggers or {}

monitorFrequency = monitorFrequency or nil
eventToDwarf = eventToDwarf or {}

function updateEventToDwarf(reportId)
if not eventToDwarf[reportId] then
eventToDwarf[reportId] = {}
end
for _,unit in ipairs(df.global.world.units.all) do
for _,reportType in ipairs(unit.reports.log) do
for _,report in ipairs(reportType) do
if report == reportId then
eventToDwarf[reportId][unit.id] = true
end
end
end
end
end

function monitor()
local reports = df.global.world.status.reports
if df.global.world.status.next_report_id-1 <= lastReport then
return
end
-- if #reports == 0 or reports[#reports-1].id <= lastReport then
-- return
-- end
_,_,start = utils.binsearch(reports,lastReport,"id")
while start < #reports and reports[start].id <= lastReport do
start = start+1
end
for i=start,#reports-1,1 do
updateEventToDwarf(reports[i].id)
for _,callBack in pairs(triggers) do
callBack(reports[i].id)
end
lastReport = reports[i].id
end
end

monitorEvery = function(n)
if n <= 0 then
print('cannot monitor onReport every '..n..' ticks.')
return
end
if monitorFrequency and monitorFrequency < n then
print('NOT decreasing frequency of onReport monitoring from every '..monitorFrequency..' ticks to every '..n..' ticks')
return
end
print('monitor onReport every '..n..' ticks')
monitorFrequency = n
repeatUtil.scheduleEvery('onReportMonitoring', n, 'ticks', monitor)
end

monitorEvery(1)

return _ENV

255 changes: 255 additions & 0 deletions plugins/lua/onStrike.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@

local _ENV = mkmodule('onStrike')

local onReport = require 'plugins.onReport'
local utils = require 'utils'

debug = debug or true

triggers = triggers or {}

function getReportString(reportId)
local report = df.report.find(reportId)
local result = report.text
local i = 1
local report2 = df.report.find(reportId+i)
while report2 and report2.flags.continuation do
result = result .. ' ' .. report2.text
i = i+1
report2 = df.report.find(reportId+i)
end
return result
end

onReport.triggers.onStrike = function(reportId)
local report = df.report.find(reportId)
if report["type"] ~= df.announcement_type.COMBAT_STRIKE_DETAILS then
return
end
if report.flags.continuation then
return
end
-- print('\n')
local fighters = {}
for unitId,_ in pairs(onReport.eventToDwarf[reportId]) do
table.insert(fighters,unitId)
end
local reportString = getReportString(reportId)
if #fighters ~= 2 then
if debug then
local ok = string.find(reportString,' skids along ')
if not ok then
print('onStrike: #fighters = ' .. #fighters)
print(reportString)
df.global.pause_state = true
end
end
return
end
local info = {}
local count = 0
fighters[1] = df.unit.find(fighters[1])
fighters[2] = df.unit.find(fighters[2])
local function getWound(fighterA,fighterB)
local wound
for i=#fighterB.body.wounds-1,0,-1 do
local w = fighterB.body.wounds[i]
if w.unit_id == fighterA.id and w.age <= 1 then
wound = w
break
end
end
--[[name,_ = tryParse(reportString,getNames(fighterA))
if not name then
wound = nil
end
--]]
return wound
end
local wound1 = getWound(fighters[1],fighters[2])
local wound2 = getWound(fighters[2],fighters[1])
local flying = string.find(reportString,'The flying')
local name1
local name2
if flying then
name1 = findAny(reportString,getNames(fighters[2]))
name2 = findAny(reportString,getNames(fighters[1]))
else
name1 = tryParse(reportString,getNames(fighters[1]))
name2 = tryParse(reportString,getNames(fighters[2]))
end
if name1 and wound1 and name2 and wound2 then
if debug then
print('ambiguous wounds: ' .. reportString)
print('fighter1 = ' .. fighters[1].id)
print('fighter2 = ' .. fighters[2].id)
df.global.pause_state = true
end
return
elseif not wound1 and not wound2 then
local ok = fighters[1].flags1.dead or fighters[2].flags1.dead or string.find(reportString,' grabs ') or string.find(reportString,'snatches at') or string.find(reportString,'glances away!') or string.find(reportString, ' shakes ')
if not ok and debug then
print('neither wound works: ' .. reportString)
print('fighter1 = ' .. fighters[1].id)
print('fighter2 = ' .. fighters[2].id)
df.global.pause_state = true
end
return
elseif not name1 and not name2 and not string.find(reportString,'The flying ') then
if debug then
print('WTF?')
print('fighter1 = ' .. fighters[1].id)
print('fighter2 = ' .. fighters[2].id)
df.global.pause_state = true
end
return
elseif name1 and wound1 then
else
local temp = fighters[1]
fighters[1] = fighters[2]
fighters[2] = temp
end
local wound = wound1 or wound2

--is it a weapon attack?
local isWeaponAttack
if getWeapon(fighters[1]) and string.find(reportString,getWeaponString(fighters[1])) then
isWeaponAttack = true
else
isWeaponAttack = false
end
isWeaponAttack = isWeaponAttack or flying
local weapon
if isWeaponAttack then
weapon = getWeapon(fighters[1])
end
-- print('triggers')
for _,trigger in pairs(triggers) do
-- print('trigger')
trigger(fighters[1],fighters[2],weapon,wound)
end
end

function myConcat(table1,table2)
local result = {}
for _,v in pairs(table1) do
table.insert(result,v)
end
for _,v in pairs(table2) do
table.insert(result,v)
end
return result
end

function getUnitAttackStrings(unit)
local result = {}
for _,attack in ipairs(unit.body.body_plan.attacks) do
table.insert(result,attack.verb_3rd..' ')
end
return result
end

function getUnitAttack(unit,parsedAttack)
for _,attack in ipairs(unit.body.body_plan.attacks) do
if attack.verb_3rd..' ' == parsedAttack then
return result
end
end
return nil
end

function getWeapon(unit)
function dumb(item)
-- print('\n')
-- print(item)
-- printall(item)
if item.mode ~= df.unit_inventory_item.T_mode.Weapon then
--print('item.mode ' .. item.mode .. ' /= Weapon ' .. df.unit_inventory_item.T_mode.Weapon)
return false
end
if item.item._type ~= df.item_weaponst then
--print('item.item._type ' .. item.item._type .. ' /= df.item_weaponst ' .. df.item_weaponst)
return false
end
return true
end
for _,item in ipairs(unit.inventory) do
if dumb(item) then
return item.item
end
end
return nil
end

function getWeaponAttackStrings(unit)
local result = {}
local weapon = getWeapon(unit)
if not weapon then
print('no weapon')
return result
end
for _,attack in ipairs(weapon.subtype.attacks) do
table.insert(result,attack.verb_3rd..' ')
end
return result
end

function getWeaponAttack(unit,parsedAttack)
local weapon = getWeapon(unit)
if not weapon then
return nil
end
for _,attack in ipairs(weapon.subtype.attacks) do
if attack.verb_3rd..' ' == parsedAttack then
return attack
end
end
return nil
end

function getNames(unit)
local result = {}
table.insert(result,unit.name.first_name .. ' ')
table.insert(result,'The '..dfhack.units.getProfessionName(unit)..' ')
table.insert(result,'the '..dfhack.units.getProfessionName(unit)..' ')
table.insert(result,'The Stray '..dfhack.units.getProfessionName(unit)..' ')
table.insert(result,'the stray '..dfhack.units.getProfessionName(unit)..' ')
return result
end

function getWeaponString(unit,suffix)
local weapon = getWeapon(unit)
if not weapon then
return ''
end
local material = getMaterialString(weapon)
return material .. ' ' .. weapon.subtype.name .. (suffix or '')
end

function getMaterialString(item)
local material = dfhack.matinfo.decode(item.mat_type,item.mat_index)
return material.material.state_name[df.matter_state.Solid]
end

function findAny(parseString,strs)
for _,str in ipairs(strs) do
if string.find(parseString,str) then
return str
end
end
return nil
end

function tryParse(parseString,strs)
for _,str in ipairs(strs) do
if string.sub(parseString,1,#str) == str then
--print('\n"' .. str .. '" matches "' .. parseString .. '"\n')
return str,string.sub(parseString,#str+1,#parseString)
end
--print('\n"' .. str .. '" doesn\'t match "' .. parseString .. '"\n')
end
return nil,nil
end

return _ENV

34 changes: 34 additions & 0 deletions plugins/lua/repeatUtil.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-- lua/plugins/repeatUtil.lua
-- author expwnent
-- vaguely based on a script by Putnam

local _ENV = mkmodule("repeatUtil")

repeating = repeating or {}

dfhack.onStateChange.repeatUtilStateChange = function(code)
if code == SC_WORLD_UNLOADED then
repeating = {}
end
end

function cancel(name)
if not repeating[name] then
return false
end
dfhack.timeout_active(repeating[name],nil)
repeating[name] = nil
return true
end

function scheduleEvery(name,time,timeUnits,func)
cancel(name)
local function helper()
func()
repeating[name] = dfhack.timeout(time,timeUnits,helper)
end
helper()
end

return _ENV

Loading

0 comments on commit 596ab0e

Please sign in to comment.