Skip to content

Instantly share code, notes, and snippets.

@Putnam3145
Created October 18, 2013 01:43
Show Gist options
  • Save Putnam3145/7035209 to your computer and use it in GitHub Desktop.
Save Putnam3145/7035209 to your computer and use it in GitHub Desktop.
A variant of Kurik Amudnil's hire-guard.lua that forces the unit to become a civ creature rather than checking.
-- Takes slaves. Hooks reactions that start with LUA_HOOK_TAKE_SLAVE. Copied very much from hire-guard.lua: http://dffd.wimbli.com/file.php?id=7785
--[[
sample reaction
[REACTION:LUA_HOOK_TAKE_SLAVE_DROW]
[NAME:Take someone ]
[BUILDING:TANNER:NONE]
[REAGENT:A:10000:COIN:NONE:INORGANIC:GOLD]
[PRODUCT:10:0:BOULDER:NONE:INORGANIC:CLAY][PRODUCT_DIMENSION:10]
[SKILL:TANNER]
product field must exist, using quantity 0 because it
doesn'tneed to actually produce anything.
product dimension determines sight radius in a circle with shadow cast visibility (default 10).
product probability + effective skill level determines chance to convert
each valid in range target, limit 1. If the first found target fails,
the second found target has the same chance etc. If all fail, reagents
are consumed as normal (respects PRESERVE_REAGENTS if present)
if no valid targets in range are found, forces PRESERVE_REAGENTS
Announcements:
success: "{guard name} has been taken as a slave!" in bright green
no targets: "{Worker Name}, {Worker Profession} cancels {reaction name}: No visible targets in range." in yellow
failed: "{Reaction name} failed." in dark red
--]]
local eventful = require 'plugins.eventful'
local mo = require 'makeown'
local fov = require 'fov'
local utils = require 'utils'
--------------------------------------------------
--------------------------------------------------
--http://lua-users.org/wiki/StringRecipes (removed indents since I am not using them)
function wrap(str, limit)--, indent, indent1)
--indent = indent or ""
--indent1 = indent1 or indent
local limit = limit or 72
local here = 1 ---#indent1
return str:gsub("(%s+)()(%S+)()", --indent1..str:gsub(
function(sp, st, word, fi)
if fi-here > limit then
here = st -- - #indent
return "\n"..word --..indent..word
end
end)
end
--------------------------------------------------
--------------------------------------------------
function isSeen(view,p)
return p.z == view.z and view[p.y][p.x] > 0
end
function findSlaveCaste(unitRaw)
for k,caste in ipairs(unitRaw.caste) do
if string.find(caste.caste_id,"SLAVE") then return k end
end
return nil
end
function cbHireGuard(reaction,unit,input_items,input_reagents,output_items,call_native)
local probability = reaction.products[0].probability + dfhack.units.getEffectiveSkill(unit,reaction.skill)
local radius = reaction.products[0].product_dimension
if radius < 1 then radius = 10 end
local view = fov.get_fov(radius,unit.pos)
local i,v,u, found, success
--find applicable unit
v = df.global.world.units.active
for i=#v-1,0,-1 do -- search list in reverse, guards/invaders are probably nearer the end of the list
u = v[i]
if u.flags1.forest and not dfhack.units.isDead(u) and not dfhack.units.isDwarf(u) and
not u.flags1.caged and isSeen(view,u.pos) and dfhack.units.isSane(u) then
--found one, check success
found = true
if math.random(100) < probability then
u.enemy.normal_race = df.global.ui.race_id
u.enemy.normal_caste = findSlaveCaste(df.global.ui.race_id) or 0 --0 is default/FEMALE, usually
mo.make_own(u)
success = true
-- override presearve reagents to consume? or let the reaction def control it?
break
end
end
end
if not found then -- no valid targets
local lines = utils.split_string( wrap( string.format("%s, %s cancels %s: No visible targets in range.",
dfhack.TranslateName(dfhack.units.getVisibleName(unit)), dfhack.units.getProfessionName(unit), reaction.name) ) , NEWLINE )
for _,v in ipairs(lines) do
dfhack.gui.showAnnouncement( v, COLOR_YELLOW)
end
for _,v in ipairs(input_reagents or {}) do
v.flags.PRESERVE_REAGENT = true
end
--unit.job.current_job.flags.suspend = true
elseif success then
dfhack.gui.showAnnouncement( dfhack.TranslateName(u.name).." has been taken as a slave!" , COLOR_GREEN, true)--color[,is_bright]
else
--if no successful targets, force reagents consumed? (same probability chance to recover reagent? for each item/stack?)
--currently let the reaction's presearve reagents determine result here.
dfhack.gui.showAnnouncement( reaction.name.." failed.", COLOR_RED)
end
call_native.value = false
end
--------------------------------------------------
--------------------------------------------------
--http://lua-users.org/wiki/StringRecipes
function string.starts(String,Start)
return string.sub(String,1,string.len(Start))==Start
end
--------------------------------------------------
--------------------------------------------------
dfhack.onStateChange.loadTakeSlave = function(code)
local registered_reactions
if code==SC_MAP_LOADED then
--registered_reactions = {}
for i,reaction in ipairs(df.global.world.raws.reactions) do
-- register each applicable reaction (to avoid doing string check
-- for every lua hook reaction (not just ours), this way uses identity check
if string.starts(reaction.code,'LUA_HOOK_TAKE_SLAVE') then
-- register reaction.code
eventful.registerReaction(reaction.code,cbHireGuard)
-- save reaction.code
--table.insert(registered_reactions,reaction.code)
registered_reactions = true
end
end
--if #registered_reactions > 0 then print('HireGuard: Loaded') end
if registered_reactions then print('HireGuard: Loaded') end
elseif code==SC_MAP_UNLOADED then
--[[ doesn't seem to be working, and probably not needed
registered_reactions = registered_reactions or {}
if #registered_reactions > 0 then print('HireGuard: Unloaded') end
for i,reaction in ipairs(registered_reactions) do
-- un register each registered reaction (to prevent persistance between
-- differing worlds (probably irrelavant, but doesn't hurt)
-- un register reaction.code
eventful.registerReaction(reaction.code,nil)
end
registered_reactions = nil -- clear registered_reactions
--]]
end
end
-- if dfhack.init has already been run, force it to think SC_WORLD_LOADED to that reactions get refreshed
if dfhack.isMapLoaded() then dfhack.onStateChange.loadTakeSlave(SC_MAP_LOADED) end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment