Merge pull request #555 from lethosor/travis

Add .travis.yml and fix whitespace issues
develop
Lethosor 2015-02-16 17:05:29 -05:00
commit e9cc242322
157 changed files with 5894 additions and 5737 deletions

@ -0,0 +1,6 @@
language: cpp
script:
- python travis/lint.py
- python travis/pr-check-base.py
notifications:
email: false

@ -1601,8 +1601,8 @@ void Core::onUpdate(color_ostream &out)
void Core::handleLoadAndUnloadScripts(color_ostream& out, state_change_event event) {
if (!df::global::world)
return;
//TODO: use different separators for windows
return;
//TODO: use different separators for windows
#ifdef _WIN32
static const std::string separator = "\\";
#else

@ -72,7 +72,7 @@ class BlockInfo
Block *mblock;
MapCache *parent;
df::map_block *block;
df::map_block_column *column; //for plants
df::map_block_column *column; //for plants
public:
enum GroundType {

@ -138,13 +138,13 @@
* only defined for compatibility. These macros should always return false
* on Windows.
*/
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO)
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO)
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
#ifdef __cplusplus
extern "C" {

@ -1,300 +1,300 @@
local _ENV = mkmodule('makeown')
--[[
'tweak makeown' as a lua include
make_own(unit) -- removes foreign flags, sets civ_id to fort civ_id, and sets clothes ownership
make_citizen(unit) -- called by make_own if unit.race == fort race
make_own(unit) -- removes foreign flags, sets civ_id to fort civ_id, and sets clothes ownership
make_citizen(unit) -- called by make_own if unit.race == fort race
eventually ought to migrate to hack/lua/plugins/tweak.lua
and local _ENV = mkmodule('plugin.tweak')
in order to link to functions in the compiled plugin (when/if they become available to lua)
eventually ought to migrate to hack/lua/plugins/tweak.lua
and local _ENV = mkmodule('plugin.tweak')
in order to link to functions in the compiled plugin (when/if they become available to lua)
--]]
local utils = require 'utils'
local function fix_clothing_ownership(unit)
-- extracted/translated from tweak makeown plugin
-- to be called by tweak-fixmigrant/makeown
-- units forced into the fort by removing the flags do not own their clothes
-- which has the result that they drop all their clothes and become unhappy because they are naked
-- so we need to make them own their clothes and add them to their uniform
local fixcount = 0 --int fixcount = 0;
for j=0,#unit.inventory-1 do --for(size_t j=0; j<unit->inventory.size(); j++)
local inv_item = unit.inventory[j] --unidf::unit_inventory_item* inv_item = unit->inventory[j];
local item = inv_item.item --df::item* item = inv_item->item;
-- unforbid items (for the case of kidnapping caravan escorts who have their stuff forbidden by default)
-- moved forbid false to inside if so that armor/weapons stay equiped
-- extracted/translated from tweak makeown plugin
-- to be called by tweak-fixmigrant/makeown
-- units forced into the fort by removing the flags do not own their clothes
-- which has the result that they drop all their clothes and become unhappy because they are naked
-- so we need to make them own their clothes and add them to their uniform
local fixcount = 0 --int fixcount = 0;
for j=0,#unit.inventory-1 do --for(size_t j=0; j<unit->inventory.size(); j++)
local inv_item = unit.inventory[j] --unidf::unit_inventory_item* inv_item = unit->inventory[j];
local item = inv_item.item --df::item* item = inv_item->item;
-- unforbid items (for the case of kidnapping caravan escorts who have their stuff forbidden by default)
-- moved forbid false to inside if so that armor/weapons stay equiped
if inv_item.mode == df.unit_inventory_item.T_mode.Worn then --if(inv_item->mode == df::unit_inventory_item::T_mode::Worn)
-- ignore armor?
-- it could be leather boots, for example, in which case it would not be nice to forbid ownership
--if(item->getEffectiveArmorLevel() != 0)
-- continue;
-- ignore armor?
-- it could be leather boots, for example, in which case it would not be nice to forbid ownership
--if(item->getEffectiveArmorLevel() != 0)
-- continue;
if not dfhack.items.getOwner(item) then --if(!Items::getOwner(item))
if dfhack.items.setOwner(item,unit) then --if(Items::setOwner(item, unit))
item.flags.forbid = false --inv_item->item->flags.bits.forbid = 0;
-- add to uniform, so they know they should wear their clothes
unit.military.uniforms[0]:insert('#',item.id) --insert_into_vector(unit->military.uniforms[0], item->id);
fixcount = fixcount + 1 --fixcount++;
if not dfhack.items.getOwner(item) then --if(!Items::getOwner(item))
if dfhack.items.setOwner(item,unit) then --if(Items::setOwner(item, unit))
item.flags.forbid = false --inv_item->item->flags.bits.forbid = 0;
-- add to uniform, so they know they should wear their clothes
unit.military.uniforms[0]:insert('#',item.id) --insert_into_vector(unit->military.uniforms[0], item->id);
fixcount = fixcount + 1 --fixcount++;
else
----out << "could not change ownership for item!" << endl;
print("Makeown: could not change ownership for an item!")
end
end
end
end
-- clear uniform_drop (without this they would drop their clothes and pick them up some time later)
-- dirty?
unit.military.uniform_drop:resize(0) --unit->military.uniform_drop.clear();
----out << "ownership for " << fixcount << " clothes fixed" << endl;
print("Makeown: claimed ownership for "..tostring(fixcount).." worn items")
--return true --return CR_OK;
----out << "could not change ownership for item!" << endl;
print("Makeown: could not change ownership for an item!")
end
end
end
end
-- clear uniform_drop (without this they would drop their clothes and pick them up some time later)
-- dirty?
unit.military.uniform_drop:resize(0) --unit->military.uniform_drop.clear();
----out << "ownership for " << fixcount << " clothes fixed" << endl;
print("Makeown: claimed ownership for "..tostring(fixcount).." worn items")
--return true --return CR_OK;
end
local function entity_link(hf, eid, do_event, add, replace_idx)
do_event = (do_event == nil) and true or do_event
add = (add == nil) and true or add
replace_idx = replace_idx or -1
do_event = (do_event == nil) and true or do_event
add = (add == nil) and true or add
replace_idx = replace_idx or -1
local link = add and df.histfig_entity_link_memberst:new() or df.histfig_entity_link_former_memberst:new()
link.entity_id = eid
if replace_idx > -1 then
local e = hf.entity_links[replace_idx]
link.link_strength = (e.link_strength > 3) and (e.link_strength - 2) or e.link_strength
hf.entity_links[replace_idx] = link -- replace member link with former member link
e:delete()
else
link.link_strength = 100
hf.entity_links:insert('#', link)
end
if do_event then
event = add and df.history_event_add_hf_entity_linkst:new() or df.history_event_remove_hf_entity_linkst:new()
event.year = df.global.cur_year
event.seconds = df.global.cur_year_tick
event.civ = eid
event.histfig = hf.id
event.link_type = 0
event.position_id = -1
event.id = df.global.hist_event_next_id
df.global.world.history.events:insert('#',event)
df.global.hist_event_next_id = df.global.hist_event_next_id + 1
end
local link = add and df.histfig_entity_link_memberst:new() or df.histfig_entity_link_former_memberst:new()
link.entity_id = eid
if replace_idx > -1 then
local e = hf.entity_links[replace_idx]
link.link_strength = (e.link_strength > 3) and (e.link_strength - 2) or e.link_strength
hf.entity_links[replace_idx] = link -- replace member link with former member link
e:delete()
else
link.link_strength = 100
hf.entity_links:insert('#', link)
end
if do_event then
event = add and df.history_event_add_hf_entity_linkst:new() or df.history_event_remove_hf_entity_linkst:new()
event.year = df.global.cur_year
event.seconds = df.global.cur_year_tick
event.civ = eid
event.histfig = hf.id
event.link_type = 0
event.position_id = -1
event.id = df.global.hist_event_next_id
df.global.world.history.events:insert('#',event)
df.global.hist_event_next_id = df.global.hist_event_next_id + 1
end
end
local function change_state(hf, site_id, pos)
hf.info.unk_14.unk_0 = 3 -- state? arrived?
hf.info.unk_14.region:assign(pos)
hf.info.unk_14.site = site_id
event = df.history_event_change_hf_statest:new()
event.year = df.global.cur_year
event.seconds = df.global.cur_year_tick
event.hfid = hf.id
event.state = 3
event.site = site_id
event.region_pos:assign(pos)
event.substate = -1; event.region = -1; event.layer = -1;
event.id = df.global.hist_event_next_id
df.global.world.history.events:insert('#',event)
df.global.hist_event_next_id = df.global.hist_event_next_id + 1
hf.info.unk_14.unk_0 = 3 -- state? arrived?
hf.info.unk_14.region:assign(pos)
hf.info.unk_14.site = site_id
event = df.history_event_change_hf_statest:new()
event.year = df.global.cur_year
event.seconds = df.global.cur_year_tick
event.hfid = hf.id
event.state = 3
event.site = site_id
event.region_pos:assign(pos)
event.substate = -1; event.region = -1; event.layer = -1;
event.id = df.global.hist_event_next_id
df.global.world.history.events:insert('#',event)
df.global.hist_event_next_id = df.global.hist_event_next_id + 1
end
function make_citizen(unit)
local dfg = df.global
local civ_id = dfg.ui.civ_id
local group_id = dfg.ui.group_id
local events = dfg.world.history.events
local fortent = dfg.ui.main.fortress_entity
local civent = fortent and df.historical_entity.find(fortent.entity_links[0].target)
-- utils.binsearch(dfg.world.entities.all, fortent.entity_links[0].target, 'id')
local event
local region_pos = df.world_site.find(dfg.ui.site_id).pos -- used with state events and hf state
local dfg = df.global
local civ_id = dfg.ui.civ_id
local group_id = dfg.ui.group_id
local events = dfg.world.history.events
local fortent = dfg.ui.main.fortress_entity
local civent = fortent and df.historical_entity.find(fortent.entity_links[0].target)
-- utils.binsearch(dfg.world.entities.all, fortent.entity_links[0].target, 'id')
local event
local region_pos = df.world_site.find(dfg.ui.site_id).pos -- used with state events and hf state
local hf
-- assume that hf id 1 and hf id 2 are equal. I am unaware of instances of when they are not.
-- occationally a unit does not have both flags set (missing flags1.important_historical_figure)
-- and I don't know what that means yet.
if unit.flags1.important_historical_figure and unit.flags2.important_historical_figure then
-- aready hf, find it (unlikely to happen)
hf = utils.binsearch(dfg.world.history.figures, unit.hist_figure_id, 'id')
--elseif unit.flags1.important_historical_figure or unit.flags2.important_historical_figure then
-- something wrong, try to fix it?
--[[
if unit.hist_figure_id == -1 then
unit.hist_figure_id = unit.hist_figure_id2
end
if unit.hist_figure_id > -1 then
unit.hist_figure_id2 = unit.hist_figure_id
unit.flags1.important_historical_figure = true
unit.flags2.important_historical_figure = true
hf = utils.binsearch(dfg.world.history.figures, unit.hist_figure_id, 'id')
else
unit.flags1.important_historical_figure = false
unit.flags2.important_historical_figure = false
end
--]]
--else
-- make one
end
--local new_hf = false
if not hf then
--new_hf = true
hf = df.historical_figure:new()
hf.profession = unit.profession
hf.race = unit.race
hf.caste = unit.caste
hf.sex = unit.sex
hf.appeared_year = dfg.cur_year
hf.born_year = unit.relations.birth_year
hf.born_seconds = unit.relations.birth_time
hf.curse_year = unit.relations.curse_year
hf.curse_seconds = unit.relations.curse_time
hf.anon_1 = unit.relations.anon_2
hf.anon_2 = unit.relations.anon_3
hf.old_year = unit.relations.old_year
hf.old_seconds = unit.relations.old_time
hf.died_year = -1
hf.died_seconds = -1
hf.name:assign(unit.name)
hf.civ_id = unit.civ_id
hf.population_id = unit.population_id
hf.breed_id = -1
hf.unit_id = unit.id
hf.id = dfg.hist_figure_next_id -- id must be set before adding links (for the events)
local hf
-- assume that hf id 1 and hf id 2 are equal. I am unaware of instances of when they are not.
-- occationally a unit does not have both flags set (missing flags1.important_historical_figure)
-- and I don't know what that means yet.
if unit.flags1.important_historical_figure and unit.flags2.important_historical_figure then
-- aready hf, find it (unlikely to happen)
hf = utils.binsearch(dfg.world.history.figures, unit.hist_figure_id, 'id')
--elseif unit.flags1.important_historical_figure or unit.flags2.important_historical_figure then
-- something wrong, try to fix it?
--[[
if unit.hist_figure_id == -1 then
unit.hist_figure_id = unit.hist_figure_id2
end
if unit.hist_figure_id > -1 then
unit.hist_figure_id2 = unit.hist_figure_id
unit.flags1.important_historical_figure = true
unit.flags2.important_historical_figure = true
hf = utils.binsearch(dfg.world.history.figures, unit.hist_figure_id, 'id')
else
unit.flags1.important_historical_figure = false
unit.flags2.important_historical_figure = false
end
--]]
--else
-- make one
end
--local new_hf = false
if not hf then
--new_hf = true
hf = df.historical_figure:new()
hf.profession = unit.profession
hf.race = unit.race
hf.caste = unit.caste
hf.sex = unit.sex
hf.appeared_year = dfg.cur_year
hf.born_year = unit.relations.birth_year
hf.born_seconds = unit.relations.birth_time
hf.curse_year = unit.relations.curse_year
hf.curse_seconds = unit.relations.curse_time
hf.anon_1 = unit.relations.anon_2
hf.anon_2 = unit.relations.anon_3
hf.old_year = unit.relations.old_year
hf.old_seconds = unit.relations.old_time
hf.died_year = -1
hf.died_seconds = -1
hf.name:assign(unit.name)
hf.civ_id = unit.civ_id
hf.population_id = unit.population_id
hf.breed_id = -1
hf.unit_id = unit.id
hf.id = dfg.hist_figure_next_id -- id must be set before adding links (for the events)
--history_event_add_hf_entity_linkst not reported for civ on starting 7
entity_link(hf, civ_id, false) -- so lets skip event here
entity_link(hf, group_id)
--history_event_add_hf_entity_linkst not reported for civ on starting 7
entity_link(hf, civ_id, false) -- so lets skip event here
entity_link(hf, group_id)
hf.info = df.historical_figure_info:new()
hf.info.unk_14 = df.historical_figure_info.T_unk_14:new() -- hf state?
--unk_14.region_id = -1; unk_14.beast_id = -1; unk_14.unk_14 = 0
hf.info.unk_14.unk_18 = -1; hf.info.unk_14.unk_1c = -1
-- set values that seem related to state and do event
change_state(hf, dfg.ui.site_id, region_pos)
hf.info = df.historical_figure_info:new()
hf.info.unk_14 = df.historical_figure_info.T_unk_14:new() -- hf state?
--unk_14.region_id = -1; unk_14.beast_id = -1; unk_14.unk_14 = 0
hf.info.unk_14.unk_18 = -1; hf.info.unk_14.unk_1c = -1
-- set values that seem related to state and do event
change_state(hf, dfg.ui.site_id, region_pos)
--lets skip skills for now
--local skills = df.historical_figure_info.T_skills:new() -- skills snap shot
-- ...
--info.skills = skills
--lets skip skills for now
--local skills = df.historical_figure_info.T_skills:new() -- skills snap shot
-- ...
--info.skills = skills
dfg.world.history.figures:insert('#', hf)
dfg.hist_figure_next_id = dfg.hist_figure_next_id + 1
dfg.world.history.figures:insert('#', hf)
dfg.hist_figure_next_id = dfg.hist_figure_next_id + 1
--new_hf_loc = df.global.world.history.figures[#df.global.world.history.figures - 1]
fortent.histfig_ids:insert('#', hf.id)
fortent.hist_figures:insert('#', hf)
civent.histfig_ids:insert('#', hf.id)
civent.hist_figures:insert('#', hf)
--new_hf_loc = df.global.world.history.figures[#df.global.world.history.figures - 1]
fortent.histfig_ids:insert('#', hf.id)
fortent.hist_figures:insert('#', hf)
civent.histfig_ids:insert('#', hf.id)
civent.hist_figures:insert('#', hf)
unit.flags1.important_historical_figure = true
unit.flags2.important_historical_figure = true
unit.hist_figure_id = hf.id
unit.hist_figure_id2 = hf.id
print("Makeown-citizen: created historical figure")
else
-- only insert into civ/fort if not already there
-- Migrants change previous histfig_entity_link_memberst to histfig_entity_link_former_memberst
-- for group entities, add link_member for new group, and reports events for remove from group,
-- remove from civ, change state, add civ, and add group
unit.flags1.important_historical_figure = true
unit.flags2.important_historical_figure = true
unit.hist_figure_id = hf.id
unit.hist_figure_id2 = hf.id
print("Makeown-citizen: created historical figure")
else
-- only insert into civ/fort if not already there
-- Migrants change previous histfig_entity_link_memberst to histfig_entity_link_former_memberst
-- for group entities, add link_member for new group, and reports events for remove from group,
-- remove from civ, change state, add civ, and add group
hf.civ_id = civ_id -- ensure current civ_id
hf.civ_id = civ_id -- ensure current civ_id
local found_civlink = false
local found_fortlink = false
local v = hf.entity_links
for k=#v-1,0,-1 do
if df.histfig_entity_link_memberst:is_instance(v[k]) then
entity_link(hf, v[k].entity_id, true, false, k)
end
end
local found_civlink = false
local found_fortlink = false
local v = hf.entity_links
for k=#v-1,0,-1 do
if df.histfig_entity_link_memberst:is_instance(v[k]) then
entity_link(hf, v[k].entity_id, true, false, k)
end
end
if hf.info and hf.info.unk_14 then
change_state(hf, dfg.ui.site_id, region_pos)
-- leave info nil if not found for now
end
if hf.info and hf.info.unk_14 then
change_state(hf, dfg.ui.site_id, region_pos)
-- leave info nil if not found for now
end
if not found_civlink then entity_link(hf,civ_id) end
if not found_fortlink then entity_link(hf,group_id) end
if not found_civlink then entity_link(hf,civ_id) end
if not found_fortlink then entity_link(hf,group_id) end
--change entity_links
local found = false
for _,v in ipairs(civent.histfig_ids) do
if v == hf.id then found = true; break end
end
if not found then
civent.histfig_ids:insert('#', hf.id)
civent.hist_figures:insert('#', hf)
end
found = false
for _,v in ipairs(fortent.histfig_ids) do
if v == hf.id then found = true; break end
end
if not found then
fortent.histfig_ids:insert('#', hf.id)
fortent.hist_figures:insert('#', hf)
end
print("Makeown-citizen: migrated historical figure")
end -- hf
--change entity_links
local found = false
for _,v in ipairs(civent.histfig_ids) do
if v == hf.id then found = true; break end
end
if not found then
civent.histfig_ids:insert('#', hf.id)
civent.hist_figures:insert('#', hf)
end
found = false
for _,v in ipairs(fortent.histfig_ids) do
if v == hf.id then found = true; break end
end
if not found then
fortent.histfig_ids:insert('#', hf.id)
fortent.hist_figures:insert('#', hf)
end
print("Makeown-citizen: migrated historical figure")
end -- hf
local nemesis = dfhack.units.getNemesis(unit)
if not nemesis then
nemesis = df.nemesis_record:new()
nemesis.figure = hf
nemesis.unit = unit
nemesis.unit_id = unit.id
nemesis.save_file_id = civent.save_file_id
nemesis.unk10, nemesis.unk11, nemesis.unk12 = -1, -1, -1
--group_leader_id = -1
nemesis.id = dfg.nemesis_next_id
nemesis.member_idx = civent.next_member_idx
civent.next_member_idx = civent.next_member_idx + 1
local nemesis = dfhack.units.getNemesis(unit)
if not nemesis then
nemesis = df.nemesis_record:new()
nemesis.figure = hf
nemesis.unit = unit
nemesis.unit_id = unit.id
nemesis.save_file_id = civent.save_file_id
nemesis.unk10, nemesis.unk11, nemesis.unk12 = -1, -1, -1
--group_leader_id = -1
nemesis.id = dfg.nemesis_next_id
nemesis.member_idx = civent.next_member_idx
civent.next_member_idx = civent.next_member_idx + 1
dfg.world.nemesis.all:insert('#', nemesis)
dfg.nemesis_next_id = dfg.nemesis_next_id + 1
dfg.world.nemesis.all:insert('#', nemesis)
dfg.nemesis_next_id = dfg.nemesis_next_id + 1
nemesis_link = df.general_ref_is_nemesisst:new()
nemesis_link.nemesis_id = nemesis.id
unit.general_refs:insert('#', nemesis_link)
nemesis_link = df.general_ref_is_nemesisst:new()
nemesis_link.nemesis_id = nemesis.id
unit.general_refs:insert('#', nemesis_link)
--new_nemesis_loc = df.global.world.nemesis.all[#df.global.world.nemesis.all - 1]
fortent.nemesis_ids:insert('#', nemesis.id)
fortent.nemesis:insert('#', nemesis)
civent.nemesis_ids:insert('#', nemesis.id)
civent.nemesis:insert('#', nemesis)
print("Makeown-citizen: created nemesis entry")
else-- only insert into civ/fort if not already there
local found = false
for _,v in ipairs(civent.nemesis_ids) do
if v == nemesis.id then found = true; break end
end
if not found then
civent.nemesis_ids:insert('#', nemesis.id)
civent.nemesis:insert('#', nemesis)
end
found = false
for _,v in ipairs(fortent.nemesis_ids) do
if v == nemesis.id then found = true; break end
end
if not found then
fortent.nemesis_ids:insert('#', nemesis.id)
fortent.nemesis:insert('#', nemesis)
end
print("Makeown-citizen: migrated nemesis entry")
end -- nemesis
--new_nemesis_loc = df.global.world.nemesis.all[#df.global.world.nemesis.all - 1]
fortent.nemesis_ids:insert('#', nemesis.id)
fortent.nemesis:insert('#', nemesis)
civent.nemesis_ids:insert('#', nemesis.id)
civent.nemesis:insert('#', nemesis)
print("Makeown-citizen: created nemesis entry")
else-- only insert into civ/fort if not already there
local found = false
for _,v in ipairs(civent.nemesis_ids) do
if v == nemesis.id then found = true; break end
end
if not found then
civent.nemesis_ids:insert('#', nemesis.id)
civent.nemesis:insert('#', nemesis)
end
found = false
for _,v in ipairs(fortent.nemesis_ids) do
if v == nemesis.id then found = true; break end
end
if not found then
fortent.nemesis_ids:insert('#', nemesis.id)
fortent.nemesis:insert('#', nemesis)
end
print("Makeown-citizen: migrated nemesis entry")
end -- nemesis
end
function make_own(unit)
--tweak makeown
unit.flags2.resident = false; unit.flags1.merchant = false; unit.flags1.forest = false;
unit.civ_id = df.global.ui.civ_id
if unit.profession == df.profession.MERCHANT then unit.profession = df.profession.TRADER end
if unit.profession2 == df.profession.MERCHANT then unit.profession2 = df.profession.TRADER end
fix_clothing_ownership(unit)
if unit.race == df.global.ui.race_id then
make_citizen(unit)
end
--tweak makeown
unit.flags2.resident = false; unit.flags1.merchant = false; unit.flags1.forest = false;
unit.civ_id = df.global.ui.civ_id
if unit.profession == df.profession.MERCHANT then unit.profession = df.profession.TRADER end
if unit.profession2 == df.profession.MERCHANT then unit.profession2 = df.profession.TRADER end
fix_clothing_ownership(unit)
if unit.race == df.global.ui.race_id then
make_citizen(unit)
end
end

@ -1616,12 +1616,12 @@ std::string Units::getCasteProfessionName(int race, int casteid, df::profession
{
std::string prof, race_prefix;
if (pid < (df::profession)0 || !is_valid_enum_item(pid))
return "";
int16_t current_race = df::global::ui->race_id;
if (df::global::gamemode && *df::global::gamemode == df::game_mode::ADVENTURE)
current_race = world->units.active[0]->race;
bool use_race_prefix = (race >= 0 && race != current_race);
if (pid < (df::profession)0 || !is_valid_enum_item(pid))
return "";
int16_t current_race = df::global::ui->race_id;
if (df::global::gamemode && *df::global::gamemode == df::game_mode::ADVENTURE)
current_race = world->units.active[0]->race;
bool use_race_prefix = (race >= 0 && race != current_race);
if (auto creature = df::creature_raw::find(race))
{

@ -9,29 +9,29 @@
class Hexsearch
{
public:
typedef std::vector<int> SearchArgType;
enum SearchConst //TODO add more
{
ANYBYTE=0x101,DWORD_,ANYDWORD,ADDRESS
};
typedef std::vector<int> SearchArgType;
enum SearchConst //TODO add more
{
ANYBYTE=0x101,DWORD_,ANYDWORD,ADDRESS
};
Hexsearch(const SearchArgType &args,char * startpos,char * endpos);
~Hexsearch();
Hexsearch(const SearchArgType &args,char * startpos,char * endpos);
~Hexsearch();
void Reset(){pos_=startpos_;};
void SetStart(char * pos){pos_=pos;};
void Reset(){pos_=startpos_;};
void SetStart(char * pos){pos_=pos;};
void * FindNext();
std::vector<void *> FindAll();
void * FindNext();
std::vector<void *> FindAll();
private:
bool Compare(int a,int b);
void ReparseArgs();
SearchArgType args_;
char * pos_,* startpos_,* endpos_;
std::vector<int> BadCharShifts,GoodSuffixShift;
void PrepareGoodSuffixTable();
void PrepareBadCharShift();
bool Compare(int a,int b);
void ReparseArgs();
SearchArgType args_;
char * pos_,* startpos_,* endpos_;
std::vector<int> BadCharShifts,GoodSuffixShift;
void PrepareGoodSuffixTable();
void PrepareBadCharShift();
};
#endif

@ -11,19 +11,19 @@ namespace lua
class Hexsearch
{
int tblid;
::Hexsearch *p;
int tblid;
::Hexsearch *p;
public:
Hexsearch(lua_State *L,int id);
~Hexsearch();
Hexsearch(lua_State *L,int id);
~Hexsearch();
int GetTableId(){return tblid;};
int GetTableId(){return tblid;};
int find(lua_State *L);
int findall(lua_State *L);
int reset(lua_State *L);
int find(lua_State *L);
int findall(lua_State *L);
int reset(lua_State *L);
DEF_LUNE(Hexsearch);
DEF_LUNE(Hexsearch);
};
void RegisterHexsearch(lua::state &st);

@ -18,25 +18,25 @@ class PlugManager
{
public:
mapPlugs GetList(){return plugs;};
mapPlugs GetList(){return plugs;};
uint32_t AddNewPlug(std::string name,uint32_t size,uint32_t loc=0);
uint32_t FindPlugin(std::string name);
static PlugManager &GetInst()
{
void *p;
p=DFHack::Core::getInstance().GetData("dfusion_manager");
if(p==0)
{
p=new PlugManager;
DFHack::Core::getInstance().RegisterData(p,"dfusion_manager");
}
return *static_cast<PlugManager*>(p);
};
{
void *p;
p=DFHack::Core::getInstance().GetData("dfusion_manager");
if(p==0)
{
p=new PlugManager;
DFHack::Core::getInstance().RegisterData(p,"dfusion_manager");
}
return *static_cast<PlugManager*>(p);
};
protected:
private:
PlugManager(){};
mapPlugs plugs;
private:
PlugManager(){};
mapPlugs plugs;
};
void RegisterMisc(lua::state &st);

@ -16,7 +16,7 @@ using std::string;
namespace lua
{
//global lua state singleton
//global lua state singleton
class glua
{
public:
@ -26,13 +26,13 @@ namespace lua
static glua *ptr;
state mystate;
};
//registers basic lua commands
//registers basic lua commands
void RegBasics(lua::state &L);
//dumps lua function trace, useless unless called from lua.
//dumps lua function trace, useless unless called from lua.
string DebugDump(lua::state &L);
//register functions, first registers into global scope, second into current table
void RegFunctions(lua::state &L,luaL_Reg const *arr);
void RegFunctionsLocal(lua::state &L,luaL_Reg const *arr);
//register functions, first registers into global scope, second into current table
void RegFunctions(lua::state &L,luaL_Reg const *arr);
void RegFunctionsLocal(lua::state &L,luaL_Reg const *arr);
}

@ -3,7 +3,7 @@
Hexsearch::Hexsearch(const SearchArgType &args,char * startpos,char * endpos):args_(args),pos_(startpos),startpos_(startpos),endpos_(endpos)
{
ReparseArgs();
ReparseArgs();
}
Hexsearch::~Hexsearch()
{
@ -11,106 +11,106 @@ Hexsearch::~Hexsearch()
}
inline bool Hexsearch::Compare(int a,int b)
{
if(b==Hexsearch::ANYBYTE)
return true;
if(a==b)
return true;
return false;
if(b==Hexsearch::ANYBYTE)
return true;
if(a==b)
return true;
return false;
}
void Hexsearch::ReparseArgs()
{
union
{
uint32_t val;
uint8_t bytes[4];
}B;
SearchArgType targ;
targ=args_;
args_.clear();
for(size_t i=0;i<targ.size();)
{
if(targ[i]==DWORD_)
{
i++;
B.val=targ[i];
for(int j=0;j<4;j++)
{
args_.push_back(B.bytes[j]);
}
i++;
}
else if (targ[i]==ANYDWORD)
{
i++;
for(int j=0;j<4;j++)
args_.push_back(ANYBYTE);
}
else
{
args_.push_back(targ[i]);
i++;
}
}
union
{
uint32_t val;
uint8_t bytes[4];
}B;
SearchArgType targ;
targ=args_;
args_.clear();
for(size_t i=0;i<targ.size();)
{
if(targ[i]==DWORD_)
{
i++;
B.val=targ[i];
for(int j=0;j<4;j++)
{
args_.push_back(B.bytes[j]);
}
i++;
}
else if (targ[i]==ANYDWORD)
{
i++;
for(int j=0;j<4;j++)
args_.push_back(ANYBYTE);
}
else
{
args_.push_back(targ[i]);
i++;
}
}
}
void * Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm
{
DFHack::Core &inst=DFHack::Core::getInstance();
DFHack::Process *p=inst.p;
uint8_t *buf;
buf=new uint8_t[args_.size()];
while(pos_<endpos_)
{
bool found=true;
p->readByte(pos_,buf[0]);
if(Compare(buf[0],args_[0]))
{
p->read(pos_,args_.size(),buf);
for(size_t i=0;i<args_.size();i++)
{
if(!Compare(buf[i],args_[i]))
{
pos_+=i;
found=false;
break;
}
}
if(found)
{
pos_+=args_.size();
delete [] buf;
return pos_-args_.size();
}
}
pos_ = pos_ + 1;
}
delete [] buf;
return 0;
DFHack::Core &inst=DFHack::Core::getInstance();
DFHack::Process *p=inst.p;
uint8_t *buf;
buf=new uint8_t[args_.size()];
while(pos_<endpos_)
{
bool found=true;
p->readByte(pos_,buf[0]);
if(Compare(buf[0],args_[0]))
{
p->read(pos_,args_.size(),buf);
for(size_t i=0;i<args_.size();i++)
{
if(!Compare(buf[i],args_[i]))
{
pos_+=i;
found=false;
break;
}
}
if(found)
{
pos_+=args_.size();
delete [] buf;
return pos_-args_.size();
}
}
pos_ = pos_ + 1;
}
delete [] buf;
return 0;
}
std::vector<void *> Hexsearch::FindAll()
{
std::vector<void *> ret;
void * cpos=pos_;
while(cpos!=0)
{
cpos=FindNext();
if(cpos!=0)
ret.push_back(cpos);
}
return ret;
std::vector<void *> ret;
void * cpos=pos_;
while(cpos!=0)
{
cpos=FindNext();
if(cpos!=0)
ret.push_back(cpos);
}
return ret;
}
void Hexsearch::PrepareBadCharShift()
{
BadCharShifts.resize(256,-1);
int i=0;
for(SearchArgType::reverse_iterator it=args_.rbegin();it!=args_.rend();it++)
{
BadCharShifts[*it]=i;
i++;
}
BadCharShifts.resize(256,-1);
int i=0;
for(SearchArgType::reverse_iterator it=args_.rbegin();it!=args_.rend();it++)
{
BadCharShifts[*it]=i;
i++;
}
}
void Hexsearch::PrepareGoodSuffixTable()
{
GoodSuffixShift.resize(args_.size()+1,0);
GoodSuffixShift.resize(args_.size()+1,0);
}

@ -2,60 +2,60 @@
int lua::Hexsearch::find(lua_State *L)
{
lua::state st(L);
void * pos=p->FindNext();
st.push(reinterpret_cast<size_t>(pos));
return 1;
void * pos=p->FindNext();
st.push(reinterpret_cast<size_t>(pos));
return 1;
}
int lua::Hexsearch::findall(lua_State *L)
{
lua::state st(L);
std::vector<void *> pos=p->FindAll();
st.newtable();
for(unsigned i=0;i<pos.size();i++)
{
st.push(i+1);
st.push(reinterpret_cast<size_t>(pos[i]));
st.settable();
}
return 1;
std::vector<void *> pos=p->FindAll();
st.newtable();
for(unsigned i=0;i<pos.size();i++)
{
st.push(i+1);
st.push(reinterpret_cast<size_t>(pos[i]));
st.settable();
}
return 1;
}
lua::Hexsearch::Hexsearch(lua_State *L,int id):tblid(id)
{
lua::state st(L);
char * start,* end;
::Hexsearch::SearchArgType args;
start= (char *)st.as<uint32_t>(1);
end=(char *)st.as<uint32_t>(2);
for(int i=3;i<=st.gettop();i++)
{
args.push_back(st.as<int>(i));
}
p=new ::Hexsearch(args,start,end);
char * start,* end;
::Hexsearch::SearchArgType args;
start= (char *)st.as<uint32_t>(1);
end=(char *)st.as<uint32_t>(2);
for(int i=3;i<=st.gettop();i++)
{
args.push_back(st.as<int>(i));
}
p=new ::Hexsearch(args,start,end);
}
lua::Hexsearch::~Hexsearch()
{
delete p;
delete p;
}
int lua::Hexsearch::reset(lua_State *L)
{
lua::state st(L);
p->Reset();
return 0;
p->Reset();
return 0;
}
IMP_LUNE(lua::Hexsearch,hexsearch);
LUNE_METHODS_START(lua::Hexsearch)
method(lua::Hexsearch,find),
method(lua::Hexsearch,findall),
method(lua::Hexsearch,reset),
method(lua::Hexsearch,find),
method(lua::Hexsearch,findall),
method(lua::Hexsearch,reset),
LUNE_METHODS_END();
#define __ADDCONST(name) st.push(::Hexsearch:: name); st.setglobal(#name)
void lua::RegisterHexsearch(lua::state &st)
{
Lune<lua::Hexsearch>::Register(st);
__ADDCONST(ANYBYTE);
__ADDCONST(ANYDWORD);
__ADDCONST(DWORD_);
Lune<lua::Hexsearch>::Register(st);
__ADDCONST(ANYBYTE);
__ADDCONST(ANYDWORD);
__ADDCONST(DWORD_);
}
#undef __ADDCONST

@ -1,21 +1,21 @@
#include "lua_Misc.h"
uint32_t lua::PlugManager::AddNewPlug(std::string name,uint32_t size,uint32_t loc)
{
void *p;
if(size!=0)
p=new unsigned char[size];
else
p=(void*)loc;
plugs[name]=p;
return (uint32_t)p;
void *p;
if(size!=0)
p=new unsigned char[size];
else
p=(void*)loc;
plugs[name]=p;
return (uint32_t)p;
}
uint32_t lua::PlugManager::FindPlugin(std::string name)
{
mapPlugs::iterator it=plugs.find(name);
if(it!=plugs.end())
return (uint32_t)it->second;
else
return 0;
mapPlugs::iterator it=plugs.find(name);
if(it!=plugs.end())
return (uint32_t)it->second;
else
return 0;
}
@ -24,10 +24,10 @@ static int LoadMod(lua_State *L)
lua::state st(L);
std::string modfile=st.as<std::string>(1);
std::string modname=st.as<std::string>(2);
uint32_t size_add=st.as<uint32_t>(0,3);
uint32_t size_add=st.as<uint32_t>(0,3);
OutFile::File f(modfile);
uint32_t size=f.GetTextSize();
uint32_t pos=lua::PlugManager::GetInst().AddNewPlug(modname,size+size_add);
uint32_t pos=lua::PlugManager::GetInst().AddNewPlug(modname,size+size_add);
char *buf;
buf=new char[size];
f.GetText(buf);
@ -133,22 +133,22 @@ static int GetMod(lua_State *L)
const luaL_Reg lua_misc_func[]=
{
{"loadmod",LoadMod},
{"getmod",GetMod},
{"loadobj",LoadObj},
{"loadobjsymbols",LoadObjSymbols},
{"findmarker",FindMarker},
{"newmod",NewMod},
{NULL,NULL}
{"loadmod",LoadMod},
{"getmod",GetMod},
{"loadobj",LoadObj},
{"loadobjsymbols",LoadObjSymbols},
{"findmarker",FindMarker},
{"newmod",NewMod},
{NULL,NULL}
};
void lua::RegisterMisc(lua::state &st)
{
st.getglobal("engine");
if(st.is<lua::nil>())
{
st.pop();
st.newtable();
}
lua::RegFunctionsLocal(st, lua_misc_func);
st.setglobal("engine");
st.getglobal("engine");
if(st.is<lua::nil>())
{
st.pop();
st.newtable();
}
lua::RegFunctionsLocal(st, lua_misc_func);
st.setglobal("engine");
}

@ -2,268 +2,268 @@
static DFHack::Process* GetProcessPtr(lua::state &st)
{
return DFHack::Core::getInstance().p;
return DFHack::Core::getInstance().p;
}
static int lua_Process_readDWord(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint32_t ret=c->readDWord( (void *) st.as<uint32_t>(1));
st.push(ret);
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint32_t ret=c->readDWord( (void *) st.as<uint32_t>(1));
st.push(ret);
return 1;
}
static int lua_Process_writeDWord(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->writeDWord((void *) st.as<uint32_t>(1),st.as<uint32_t>(2));
return 0;
return 0;
}
static int lua_Process_readFloat(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
float ret=c->readFloat((void *) st.as<uint32_t>(1));
st.push(ret);
return 1;
st.push(ret);
return 1;
}
static int lua_Process_readWord(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint16_t ret=c->readWord((void *) st.as<uint32_t>(1));
st.push(ret);
return 1;
st.push(ret);
return 1;
}
static int lua_Process_writeWord(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->writeWord((void *) st.as<uint32_t>(1),st.as<uint16_t>(2));
return 0;
return 0;
}
static int lua_Process_readByte(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint8_t ret=c->readByte((void *) st.as<uint32_t>(1));
st.push(ret);
return 1;
st.push(ret);
return 1;
}
static int lua_Process_writeByte(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->writeByte((void *) st.as<uint32_t>(1),st.as<uint8_t>(2));
return 0;
return 0;
}
static int lua_Process_read(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
size_t len=st.as<uint32_t>(2);
uint8_t* buf;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
size_t len=st.as<uint32_t>(2);
uint8_t* buf;
if(!st.is<lua::nil>(3))
buf=(uint8_t*)lua_touserdata(st,3);
else
buf=new uint8_t[len];
if(!st.is<lua::nil>(3))
buf=(uint8_t*)lua_touserdata(st,3);
else
buf=new uint8_t[len];
c->read((void *) st.as<uint32_t>(1),len,buf);
st.pushlightuserdata(buf);
return 1;
st.pushlightuserdata(buf);
return 1;
}
static int lua_Process_write(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c-> write((void *) st.as<uint32_t>(1),st.as<uint32_t>(2),static_cast<uint8_t*>(lua_touserdata(st,3)));
return 0;
return 0;
}
static int lua_Process_readSTLString (lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->readSTLString((void *) st.as<uint32_t>(1));
st.push(r);
return 1;
st.push(r);
return 1;
}
static int lua_Process_writeSTLString(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->writeSTLString((void *) st.as<uint32_t>(1),st.as<std::string>(2));
return 0;
return 0;
}
static int lua_Process_copySTLString(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
c->copySTLString((void *) st.as<uint32_t>(1),st.as<uint32_t>(2));
return 0;
return 0;
}
static int lua_Process_doReadClassName(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->doReadClassName((void*)st.as<size_t>(1));
st.push(r);
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->doReadClassName((void*)st.as<size_t>(1));
st.push(r);
return 1;
}
static int lua_Process_readClassName(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->readClassName((void*)st.as<size_t>(1));
st.push(r);
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->readClassName((void*)st.as<size_t>(1));
st.push(r);
return 1;
}
static int lua_Process_readCString (lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string r=c->readCString((void *) st.as<uint32_t>(1));
st.push(r);
return 1;
st.push(r);
return 1;
}
static int lua_Process_isSuspended(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
st.push(c->isSuspended());
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
st.push(c->isSuspended());
return 1;
}
static int lua_Process_isIdentified(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
st.push(c->isIdentified());
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
st.push(c->isIdentified());
return 1;
}
static int lua_Process_getMemRanges(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::vector<DFHack::t_memrange> ranges;
c->getMemRanges(ranges);
st.newtable();
for(size_t i=0;i<ranges.size();i++)
{
st.push(i);
st.newtable();
st.push((uint32_t)ranges[i].start); // WARNING!! lua has only 32bit numbers, possible loss of data!!
st.setfield("start");
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::vector<DFHack::t_memrange> ranges;
c->getMemRanges(ranges);
st.newtable();
for(size_t i=0;i<ranges.size();i++)
{
st.push(i);
st.newtable();
st.push((uint32_t)ranges[i].start); // WARNING!! lua has only 32bit numbers, possible loss of data!!
st.setfield("start");
st.push((uint32_t)ranges[i].end);
st.setfield("end");
st.push(std::string(ranges[i].name));
st.setfield("name");
st.push(ranges[i].read);
st.setfield("read");
st.push(ranges[i].write);
st.setfield("write");
st.push(ranges[i].execute);
st.setfield("execute");
st.push(ranges[i].shared);
st.setfield("shared");
st.push(ranges[i].valid);
st.setfield("valid");
st.settable();
}
return 1;
st.setfield("end");
st.push(std::string(ranges[i].name));
st.setfield("name");
st.push(ranges[i].read);
st.setfield("read");
st.push(ranges[i].write);
st.setfield("write");
st.push(ranges[i].execute);
st.setfield("execute");
st.push(ranges[i].shared);
st.setfield("shared");
st.push(ranges[i].valid);
st.setfield("valid");
st.settable();
}
return 1;
}
static int lua_Process_getBase(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint32_t base=c->getBase();
st.push(base);
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
uint32_t base=c->getBase();
st.push(base);
return 1;
}
/*static int lua_Process_getPID(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
int ret=c->getPID();
st.push(ret);
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
int ret=c->getPID();
st.push(ret);
return 1;
}*/
static int lua_Process_getPath(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string ret=c->getPath();
st.push(ret);
return 1;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
std::string ret=c->getPath();
st.push(ret);
return 1;
}
static int lua_Process_setPermisions(lua_State *S)
{
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
DFHack::t_memrange range,trange;
lua::state st(S);
DFHack::Process* c=GetProcessPtr(st);
DFHack::t_memrange range,trange;
st.getfield("start",1);
range.start= (void *)st.as<uint64_t>();
st.pop();
st.getfield("end",1);
range.end= (void *)st.as<uint64_t>();
st.pop();
st.getfield("start",1);
range.start= (void *)st.as<uint64_t>();
st.pop();
st.getfield("end",1);
range.end= (void *)st.as<uint64_t>();
st.pop();
st.getfield("read",2);
trange.read=st.as<bool>();
st.pop();
st.getfield("write",2);
trange.write=st.as<bool>();
st.pop();
st.getfield("execute",2);
trange.execute=st.as<bool>();
st.pop();
st.getfield("read",2);
trange.read=st.as<bool>();
st.pop();
st.getfield("write",2);
trange.write=st.as<bool>();
st.pop();
st.getfield("execute",2);
trange.execute=st.as<bool>();
st.pop();
c->setPermisions(range,trange);
c->setPermisions(range,trange);
return 0;
return 0;
}
#define PROC_FUNC(name) {#name,lua_Process_ ## name}
const luaL_Reg lua_process_func[]=
{
PROC_FUNC(readDWord),
PROC_FUNC(writeDWord),
PROC_FUNC(readFloat),
PROC_FUNC(readWord),
PROC_FUNC(writeWord),
PROC_FUNC(readByte),
PROC_FUNC(writeByte),
PROC_FUNC(read),
PROC_FUNC(write),
PROC_FUNC(readSTLString),
PROC_FUNC(writeSTLString),
PROC_FUNC(copySTLString),
PROC_FUNC(doReadClassName),
PROC_FUNC(readClassName),
PROC_FUNC(readCString ),
PROC_FUNC(isSuspended),
PROC_FUNC(isIdentified),
PROC_FUNC(getMemRanges),
PROC_FUNC(getBase),
//PROC_FUNC(getPID), //not implemented
PROC_FUNC(getPath),
PROC_FUNC(setPermisions),
{NULL,NULL}
PROC_FUNC(readDWord),
PROC_FUNC(writeDWord),
PROC_FUNC(readFloat),
PROC_FUNC(readWord),
PROC_FUNC(writeWord),
PROC_FUNC(readByte),
PROC_FUNC(writeByte),
PROC_FUNC(read),
PROC_FUNC(write),
PROC_FUNC(readSTLString),
PROC_FUNC(writeSTLString),
PROC_FUNC(copySTLString),
PROC_FUNC(doReadClassName),
PROC_FUNC(readClassName),
PROC_FUNC(readCString ),
PROC_FUNC(isSuspended),
PROC_FUNC(isIdentified),
PROC_FUNC(getMemRanges),
PROC_FUNC(getBase),
//PROC_FUNC(getPID), //not implemented
PROC_FUNC(getPath),
PROC_FUNC(setPermisions),
{NULL,NULL}
};
#undef PROC_FUNC
void lua::RegisterProcess(lua::state &st)
{
st.getglobal("Process");
if(st.is<lua::nil>())
{
st.pop();
st.newtable();
}
st.getglobal("Process");
if(st.is<lua::nil>())
{
st.pop();
st.newtable();
}
lua::RegFunctionsLocal(st, lua_process_func);
lua::RegFunctionsLocal(st, lua_process_func);
st.setglobal("Process");
st.setglobal("Process");
}

File diff suppressed because it is too large Load Diff

@ -529,124 +529,124 @@ struct dwarf_info_t
static df::unit_labor hauling_labor_map[] =
{
df::unit_labor::HAUL_ITEM, /* BAR */
df::unit_labor::HAUL_STONE, /* SMALLGEM */
df::unit_labor::HAUL_ITEM, /* BLOCKS */
df::unit_labor::HAUL_STONE, /* ROUGH */
df::unit_labor::HAUL_STONE, /* BOULDER */
df::unit_labor::HAUL_WOOD, /* WOOD */
df::unit_labor::HAUL_FURNITURE, /* DOOR */
df::unit_labor::HAUL_FURNITURE, /* FLOODGATE */
df::unit_labor::HAUL_FURNITURE, /* BED */
df::unit_labor::HAUL_FURNITURE, /* CHAIR */
df::unit_labor::HAUL_ITEM, /* CHAIN */
df::unit_labor::HAUL_ITEM, /* FLASK */
df::unit_labor::HAUL_ITEM, /* GOBLET */
df::unit_labor::HAUL_ITEM, /* INSTRUMENT */
df::unit_labor::HAUL_ITEM, /* TOY */
df::unit_labor::HAUL_FURNITURE, /* WINDOW */
df::unit_labor::HAUL_ANIMAL, /* CAGE */
df::unit_labor::HAUL_ITEM, /* BARREL */
df::unit_labor::HAUL_ITEM, /* BUCKET */
df::unit_labor::HAUL_ANIMAL, /* ANIMALTRAP */
df::unit_labor::HAUL_FURNITURE, /* TABLE */
df::unit_labor::HAUL_FURNITURE, /* COFFIN */
df::unit_labor::HAUL_FURNITURE, /* STATUE */
df::unit_labor::HAUL_REFUSE, /* CORPSE */
df::unit_labor::HAUL_ITEM, /* WEAPON */
df::unit_labor::HAUL_ITEM, /* ARMOR */
df::unit_labor::HAUL_ITEM, /* SHOES */
df::unit_labor::HAUL_ITEM, /* SHIELD */
df::unit_labor::HAUL_ITEM, /* HELM */
df::unit_labor::HAUL_ITEM, /* GLOVES */
df::unit_labor::HAUL_FURNITURE, /* BOX */
df::unit_labor::HAUL_ITEM, /* BIN */
df::unit_labor::HAUL_FURNITURE, /* ARMORSTAND */
df::unit_labor::HAUL_FURNITURE, /* WEAPONRACK */
df::unit_labor::HAUL_FURNITURE, /* CABINET */
df::unit_labor::HAUL_ITEM, /* FIGURINE */
df::unit_labor::HAUL_ITEM, /* AMULET */
df::unit_labor::HAUL_ITEM, /* SCEPTER */
df::unit_labor::HAUL_ITEM, /* AMMO */
df::unit_labor::HAUL_ITEM, /* CROWN */
df::unit_labor::HAUL_ITEM, /* RING */
df::unit_labor::HAUL_ITEM, /* EARRING */
df::unit_labor::HAUL_ITEM, /* BRACELET */
df::unit_labor::HAUL_ITEM, /* GEM */
df::unit_labor::HAUL_FURNITURE, /* ANVIL */
df::unit_labor::HAUL_REFUSE, /* CORPSEPIECE */
df::unit_labor::HAUL_REFUSE, /* REMAINS */
df::unit_labor::HAUL_FOOD, /* MEAT */
df::unit_labor::HAUL_FOOD, /* FISH */
df::unit_labor::HAUL_FOOD, /* FISH_RAW */
df::unit_labor::HAUL_REFUSE, /* VERMIN */
df::unit_labor::HAUL_ITEM, /* PET */
df::unit_labor::HAUL_FOOD, /* SEEDS */
df::unit_labor::HAUL_FOOD, /* PLANT */
df::unit_labor::HAUL_ITEM, /* SKIN_TANNED */
df::unit_labor::HAUL_FOOD, /* LEAVES */
df::unit_labor::HAUL_ITEM, /* THREAD */
df::unit_labor::HAUL_ITEM, /* CLOTH */
df::unit_labor::HAUL_ITEM, /* TOTEM */
df::unit_labor::HAUL_ITEM, /* PANTS */
df::unit_labor::HAUL_ITEM, /* BACKPACK */
df::unit_labor::HAUL_ITEM, /* QUIVER */
df::unit_labor::HAUL_FURNITURE, /* CATAPULTPARTS */
df::unit_labor::HAUL_FURNITURE, /* BALLISTAPARTS */
df::unit_labor::HAUL_FURNITURE, /* SIEGEAMMO */
df::unit_labor::HAUL_FURNITURE, /* BALLISTAARROWHEAD */
df::unit_labor::HAUL_FURNITURE, /* TRAPPARTS */
df::unit_labor::HAUL_FURNITURE, /* TRAPCOMP */
df::unit_labor::HAUL_FOOD, /* DRINK */
df::unit_labor::HAUL_FOOD, /* POWDER_MISC */
df::unit_labor::HAUL_FOOD, /* CHEESE */
df::unit_labor::HAUL_FOOD, /* FOOD */
df::unit_labor::HAUL_FOOD, /* LIQUID_MISC */
df::unit_labor::HAUL_ITEM, /* COIN */
df::unit_labor::HAUL_FOOD, /* GLOB */
df::unit_labor::HAUL_STONE, /* ROCK */
df::unit_labor::HAUL_FURNITURE, /* PIPE_SECTION */
df::unit_labor::HAUL_FURNITURE, /* HATCH_COVER */
df::unit_labor::HAUL_FURNITURE, /* GRATE */
df::unit_labor::HAUL_FURNITURE, /* QUERN */
df::unit_labor::HAUL_FURNITURE, /* MILLSTONE */
df::unit_labor::HAUL_ITEM, /* SPLINT */
df::unit_labor::HAUL_ITEM, /* CRUTCH */
df::unit_labor::HAUL_FURNITURE, /* TRACTION_BENCH */
df::unit_labor::HAUL_ITEM, /* ORTHOPEDIC_CAST */
df::unit_labor::HAUL_ITEM, /* TOOL */
df::unit_labor::HAUL_FURNITURE, /* SLAB */
df::unit_labor::HAUL_FOOD, /* EGG */
df::unit_labor::HAUL_ITEM, /* BOOK */
df::unit_labor::HAUL_ITEM, /* BAR */
df::unit_labor::HAUL_STONE, /* SMALLGEM */
df::unit_labor::HAUL_ITEM, /* BLOCKS */
df::unit_labor::HAUL_STONE, /* ROUGH */
df::unit_labor::HAUL_STONE, /* BOULDER */
df::unit_labor::HAUL_WOOD, /* WOOD */
df::unit_labor::HAUL_FURNITURE, /* DOOR */
df::unit_labor::HAUL_FURNITURE, /* FLOODGATE */
df::unit_labor::HAUL_FURNITURE, /* BED */
df::unit_labor::HAUL_FURNITURE, /* CHAIR */
df::unit_labor::HAUL_ITEM, /* CHAIN */
df::unit_labor::HAUL_ITEM, /* FLASK */
df::unit_labor::HAUL_ITEM, /* GOBLET */
df::unit_labor::HAUL_ITEM, /* INSTRUMENT */
df::unit_labor::HAUL_ITEM, /* TOY */
df::unit_labor::HAUL_FURNITURE, /* WINDOW */
df::unit_labor::HAUL_ANIMAL, /* CAGE */
df::unit_labor::HAUL_ITEM, /* BARREL */
df::unit_labor::HAUL_ITEM, /* BUCKET */
df::unit_labor::HAUL_ANIMAL, /* ANIMALTRAP */
df::unit_labor::HAUL_FURNITURE, /* TABLE */
df::unit_labor::HAUL_FURNITURE, /* COFFIN */
df::unit_labor::HAUL_FURNITURE, /* STATUE */
df::unit_labor::HAUL_REFUSE, /* CORPSE */
df::unit_labor::HAUL_ITEM, /* WEAPON */
df::unit_labor::HAUL_ITEM, /* ARMOR */
df::unit_labor::HAUL_ITEM, /* SHOES */
df::unit_labor::HAUL_ITEM, /* SHIELD */
df::unit_labor::HAUL_ITEM, /* HELM */
df::unit_labor::HAUL_ITEM, /* GLOVES */
df::unit_labor::HAUL_FURNITURE, /* BOX */
df::unit_labor::HAUL_ITEM, /* BIN */
df::unit_labor::HAUL_FURNITURE, /* ARMORSTAND */
df::unit_labor::HAUL_FURNITURE, /* WEAPONRACK */
df::unit_labor::HAUL_FURNITURE, /* CABINET */
df::unit_labor::HAUL_ITEM, /* FIGURINE */
df::unit_labor::HAUL_ITEM, /* AMULET */
df::unit_labor::HAUL_ITEM, /* SCEPTER */
df::unit_labor::HAUL_ITEM, /* AMMO */
df::unit_labor::HAUL_ITEM, /* CROWN */
df::unit_labor::HAUL_ITEM, /* RING */
df::unit_labor::HAUL_ITEM, /* EARRING */
df::unit_labor::HAUL_ITEM, /* BRACELET */
df::unit_labor::HAUL_ITEM, /* GEM */
df::unit_labor::HAUL_FURNITURE, /* ANVIL */
df::unit_labor::HAUL_REFUSE, /* CORPSEPIECE */
df::unit_labor::HAUL_REFUSE, /* REMAINS */
df::unit_labor::HAUL_FOOD, /* MEAT */
df::unit_labor::HAUL_FOOD, /* FISH */
df::unit_labor::HAUL_FOOD, /* FISH_RAW */
df::unit_labor::HAUL_REFUSE, /* VERMIN */
df::unit_labor::HAUL_ITEM, /* PET */
df::unit_labor::HAUL_FOOD, /* SEEDS */
df::unit_labor::HAUL_FOOD, /* PLANT */
df::unit_labor::HAUL_ITEM, /* SKIN_TANNED */
df::unit_labor::HAUL_FOOD, /* LEAVES */
df::unit_labor::HAUL_ITEM, /* THREAD */
df::unit_labor::HAUL_ITEM, /* CLOTH */
df::unit_labor::HAUL_ITEM, /* TOTEM */
df::unit_labor::HAUL_ITEM, /* PANTS */
df::unit_labor::HAUL_ITEM, /* BACKPACK */
df::unit_labor::HAUL_ITEM, /* QUIVER */
df::unit_labor::HAUL_FURNITURE, /* CATAPULTPARTS */
df::unit_labor::HAUL_FURNITURE, /* BALLISTAPARTS */
df::unit_labor::HAUL_FURNITURE, /* SIEGEAMMO */
df::unit_labor::HAUL_FURNITURE, /* BALLISTAARROWHEAD */
df::unit_labor::HAUL_FURNITURE, /* TRAPPARTS */
df::unit_labor::HAUL_FURNITURE, /* TRAPCOMP */
df::unit_labor::HAUL_FOOD, /* DRINK */
df::unit_labor::HAUL_FOOD, /* POWDER_MISC */
df::unit_labor::HAUL_FOOD, /* CHEESE */
df::unit_labor::HAUL_FOOD, /* FOOD */
df::unit_labor::HAUL_FOOD, /* LIQUID_MISC */
df::unit_labor::HAUL_ITEM, /* COIN */
df::unit_labor::HAUL_FOOD, /* GLOB */
df::unit_labor::HAUL_STONE, /* ROCK */
df::unit_labor::HAUL_FURNITURE, /* PIPE_SECTION */
df::unit_labor::HAUL_FURNITURE, /* HATCH_COVER */
df::unit_labor::HAUL_FURNITURE, /* GRATE */
df::unit_labor::HAUL_FURNITURE, /* QUERN */
df::unit_labor::HAUL_FURNITURE, /* MILLSTONE */
df::unit_labor::HAUL_ITEM, /* SPLINT */
df::unit_labor::HAUL_ITEM, /* CRUTCH */
df::unit_labor::HAUL_FURNITURE, /* TRACTION_BENCH */
df::unit_labor::HAUL_ITEM, /* ORTHOPEDIC_CAST */
df::unit_labor::HAUL_ITEM, /* TOOL */
df::unit_labor::HAUL_FURNITURE, /* SLAB */
df::unit_labor::HAUL_FOOD, /* EGG */
df::unit_labor::HAUL_ITEM, /* BOOK */
};
static df::unit_labor workshop_build_labor[] =
{
/* Carpenters */ df::unit_labor::CARPENTER,
/* Farmers */ df::unit_labor::PROCESS_PLANT,
/* Masons */ df::unit_labor::MASON,
/* Craftsdwarfs */ df::unit_labor::STONE_CRAFT,
/* Jewelers */ df::unit_labor::CUT_GEM,
/* MetalsmithsForge */ df::unit_labor::METAL_CRAFT,
/* MagmaForge */ df::unit_labor::METAL_CRAFT,
/* Bowyers */ df::unit_labor::BOWYER,
/* Mechanics */ df::unit_labor::MECHANIC,
/* Siege */ df::unit_labor::SIEGECRAFT,
/* Butchers */ df::unit_labor::BUTCHER,
/* Leatherworks */ df::unit_labor::LEATHER,
/* Tanners */ df::unit_labor::TANNER,
/* Clothiers */ df::unit_labor::CLOTHESMAKER,
/* Fishery */ df::unit_labor::CLEAN_FISH,
/* Still */ df::unit_labor::BREWER,
/* Loom */ df::unit_labor::WEAVER,
/* Quern */ df::unit_labor::MILLER,
/* Kennels */ df::unit_labor::ANIMALTRAIN,
/* Kitchen */ df::unit_labor::COOK,
/* Ashery */ df::unit_labor::LYE_MAKING,
/* Dyers */ df::unit_labor::DYER,
/* Millstone */ df::unit_labor::MILLER,
/* Custom */ df::unit_labor::NONE,
/* Tool */ df::unit_labor::NONE
/* Carpenters */ df::unit_labor::CARPENTER,
/* Farmers */ df::unit_labor::PROCESS_PLANT,
/* Masons */ df::unit_labor::MASON,
/* Craftsdwarfs */ df::unit_labor::STONE_CRAFT,
/* Jewelers */ df::unit_labor::CUT_GEM,
/* MetalsmithsForge */ df::unit_labor::METAL_CRAFT,
/* MagmaForge */ df::unit_labor::METAL_CRAFT,
/* Bowyers */ df::unit_labor::BOWYER,
/* Mechanics */ df::unit_labor::MECHANIC,
/* Siege */ df::unit_labor::SIEGECRAFT,
/* Butchers */ df::unit_labor::BUTCHER,
/* Leatherworks */ df::unit_labor::LEATHER,
/* Tanners */ df::unit_labor::TANNER,
/* Clothiers */ df::unit_labor::CLOTHESMAKER,
/* Fishery */ df::unit_labor::CLEAN_FISH,
/* Still */ df::unit_labor::BREWER,
/* Loom */ df::unit_labor::WEAVER,
/* Quern */ df::unit_labor::MILLER,
/* Kennels */ df::unit_labor::ANIMALTRAIN,
/* Kitchen */ df::unit_labor::COOK,
/* Ashery */ df::unit_labor::LYE_MAKING,
/* Dyers */ df::unit_labor::DYER,
/* Millstone */ df::unit_labor::MILLER,
/* Custom */ df::unit_labor::NONE,
/* Tool */ df::unit_labor::NONE
};
static df::building* get_building_from_job(df::job* j)
@ -1090,7 +1090,7 @@ public:
JobLaborMapper()
{
jlfunc* jlf_hauling = new jlfunc_hauling();
jlfunc* jlf_hauling = new jlfunc_hauling();
jlfunc* jlf_make_furniture = new jlfunc_make(df::unit_labor::FORGE_FURNITURE);
jlfunc* jlf_make_object = new jlfunc_make(df::unit_labor::METAL_CRAFT);
jlfunc* jlf_make_armor = new jlfunc_make(df::unit_labor::FORGE_ARMOR);
@ -1098,236 +1098,236 @@ public:
jlfunc* jlf_no_labor = jlf_const(df::unit_labor::NONE);
job_to_labor_table[df::job_type::CarveFortification] = jlf_const(df::unit_labor::DETAIL);
job_to_labor_table[df::job_type::DetailWall] = jlf_const(df::unit_labor::DETAIL);
job_to_labor_table[df::job_type::DetailFloor] = jlf_const(df::unit_labor::DETAIL);
job_to_labor_table[df::job_type::Dig] = jlf_const(df::unit_labor::MINE);
job_to_labor_table[df::job_type::CarveUpwardStaircase] = jlf_const(df::unit_labor::MINE);
job_to_labor_table[df::job_type::CarveFortification] = jlf_const(df::unit_labor::DETAIL);
job_to_labor_table[df::job_type::DetailWall] = jlf_const(df::unit_labor::DETAIL);
job_to_labor_table[df::job_type::DetailFloor] = jlf_const(df::unit_labor::DETAIL);
job_to_labor_table[df::job_type::Dig] = jlf_const(df::unit_labor::MINE);
job_to_labor_table[df::job_type::CarveUpwardStaircase] = jlf_const(df::unit_labor::MINE);
job_to_labor_table[df::job_type::CarveDownwardStaircase] = jlf_const(df::unit_labor::MINE);
job_to_labor_table[df::job_type::CarveUpDownStaircase] = jlf_const(df::unit_labor::MINE);
job_to_labor_table[df::job_type::CarveRamp] = jlf_const(df::unit_labor::MINE);
job_to_labor_table[df::job_type::DigChannel] = jlf_const(df::unit_labor::MINE);
job_to_labor_table[df::job_type::FellTree] = jlf_const(df::unit_labor::CUTWOOD);
job_to_labor_table[df::job_type::GatherPlants] = jlf_const(df::unit_labor::HERBALIST);
job_to_labor_table[df::job_type::RemoveConstruction] = jlf_no_labor;
job_to_labor_table[df::job_type::CollectWebs] = jlf_const(df::unit_labor::WEAVER);
job_to_labor_table[df::job_type::BringItemToDepot] = jlf_no_labor;
job_to_labor_table[df::job_type::BringItemToShop] = jlf_no_labor;
job_to_labor_table[df::job_type::Eat] = jlf_no_labor;
job_to_labor_table[df::job_type::GetProvisions] = jlf_no_labor;
job_to_labor_table[df::job_type::Drink] = jlf_no_labor;
job_to_labor_table[df::job_type::Drink2] = jlf_no_labor;
job_to_labor_table[df::job_type::FillWaterskin] = jlf_no_labor;
job_to_labor_table[df::job_type::FillWaterskin2] = jlf_no_labor;
job_to_labor_table[df::job_type::Sleep] = jlf_no_labor;
job_to_labor_table[df::job_type::CollectSand] = jlf_const(df::unit_labor::HAUL_ITEM);
job_to_labor_table[df::job_type::Fish] = jlf_const(df::unit_labor::FISH);
job_to_labor_table[df::job_type::Hunt] = jlf_const(df::unit_labor::HUNT);
job_to_labor_table[df::job_type::HuntVermin] = jlf_no_labor;
job_to_labor_table[df::job_type::Kidnap] = jlf_no_labor;
job_to_labor_table[df::job_type::BeatCriminal] = jlf_no_labor;
job_to_labor_table[df::job_type::StartingFistFight] = jlf_no_labor;
job_to_labor_table[df::job_type::CollectTaxes] = jlf_no_labor;
job_to_labor_table[df::job_type::GuardTaxCollector] = jlf_no_labor;
job_to_labor_table[df::job_type::CatchLiveLandAnimal] = jlf_const(df::unit_labor::HUNT);
job_to_labor_table[df::job_type::CatchLiveFish] = jlf_const(df::unit_labor::FISH);
job_to_labor_table[df::job_type::ReturnKill] = jlf_no_labor;
job_to_labor_table[df::job_type::CheckChest] = jlf_no_labor;
job_to_labor_table[df::job_type::StoreOwnedItem] = jlf_no_labor;
job_to_labor_table[df::job_type::PlaceItemInTomb] = jlf_const(df::unit_labor::HAUL_BODY);
job_to_labor_table[df::job_type::StoreItemInStockpile] = jlf_hauling;
job_to_labor_table[df::job_type::StoreItemInBag] = jlf_hauling;
job_to_labor_table[df::job_type::StoreItemInHospital] = jlf_hauling;
job_to_labor_table[df::job_type::StoreItemInChest] = jlf_hauling;
job_to_labor_table[df::job_type::StoreItemInCabinet] = jlf_hauling;
job_to_labor_table[df::job_type::StoreWeapon] = jlf_hauling;
job_to_labor_table[df::job_type::StoreArmor] = jlf_hauling;
job_to_labor_table[df::job_type::StoreItemInBarrel] = jlf_hauling;
job_to_labor_table[df::job_type::StoreItemInBin] = jlf_const(df::unit_labor::HAUL_ITEM);
job_to_labor_table[df::job_type::SeekArtifact] = jlf_no_labor;
job_to_labor_table[df::job_type::SeekInfant] = jlf_no_labor;
job_to_labor_table[df::job_type::AttendParty] = jlf_no_labor;
job_to_labor_table[df::job_type::GoShopping] = jlf_no_labor;
job_to_labor_table[df::job_type::GoShopping2] = jlf_no_labor;
job_to_labor_table[df::job_type::Clean] = jlf_const(df::unit_labor::CLEAN);
job_to_labor_table[df::job_type::Rest] = jlf_no_labor;
job_to_labor_table[df::job_type::PickupEquipment] = jlf_no_labor;
job_to_labor_table[df::job_type::DumpItem] = jlf_const(df::unit_labor::HAUL_REFUSE);
job_to_labor_table[df::job_type::StrangeMoodCrafter] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodJeweller] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodForge] = jlf_no_labor;
job_to_labor_table[df::job_type::CarveUpDownStaircase] = jlf_const(df::unit_labor::MINE);
job_to_labor_table[df::job_type::CarveRamp] = jlf_const(df::unit_labor::MINE);
job_to_labor_table[df::job_type::DigChannel] = jlf_const(df::unit_labor::MINE);
job_to_labor_table[df::job_type::FellTree] = jlf_const(df::unit_labor::CUTWOOD);
job_to_labor_table[df::job_type::GatherPlants] = jlf_const(df::unit_labor::HERBALIST);
job_to_labor_table[df::job_type::RemoveConstruction] = jlf_no_labor;
job_to_labor_table[df::job_type::CollectWebs] = jlf_const(df::unit_labor::WEAVER);
job_to_labor_table[df::job_type::BringItemToDepot] = jlf_no_labor;
job_to_labor_table[df::job_type::BringItemToShop] = jlf_no_labor;
job_to_labor_table[df::job_type::Eat] = jlf_no_labor;
job_to_labor_table[df::job_type::GetProvisions] = jlf_no_labor;
job_to_labor_table[df::job_type::Drink] = jlf_no_labor;
job_to_labor_table[df::job_type::Drink2] = jlf_no_labor;
job_to_labor_table[df::job_type::FillWaterskin] = jlf_no_labor;
job_to_labor_table[df::job_type::FillWaterskin2] = jlf_no_labor;
job_to_labor_table[df::job_type::Sleep] = jlf_no_labor;
job_to_labor_table[df::job_type::CollectSand] = jlf_const(df::unit_labor::HAUL_ITEM);
job_to_labor_table[df::job_type::Fish] = jlf_const(df::unit_labor::FISH);
job_to_labor_table[df::job_type::Hunt] = jlf_const(df::unit_labor::HUNT);
job_to_labor_table[df::job_type::HuntVermin] = jlf_no_labor;
job_to_labor_table[df::job_type::Kidnap] = jlf_no_labor;
job_to_labor_table[df::job_type::BeatCriminal] = jlf_no_labor;
job_to_labor_table[df::job_type::StartingFistFight] = jlf_no_labor;
job_to_labor_table[df::job_type::CollectTaxes] = jlf_no_labor;
job_to_labor_table[df::job_type::GuardTaxCollector] = jlf_no_labor;
job_to_labor_table[df::job_type::CatchLiveLandAnimal] = jlf_const(df::unit_labor::HUNT);
job_to_labor_table[df::job_type::CatchLiveFish] = jlf_const(df::unit_labor::FISH);
job_to_labor_table[df::job_type::ReturnKill] = jlf_no_labor;
job_to_labor_table[df::job_type::CheckChest] = jlf_no_labor;
job_to_labor_table[df::job_type::StoreOwnedItem] = jlf_no_labor;
job_to_labor_table[df::job_type::PlaceItemInTomb] = jlf_const(df::unit_labor::HAUL_BODY);
job_to_labor_table[df::job_type::StoreItemInStockpile] = jlf_hauling;
job_to_labor_table[df::job_type::StoreItemInBag] = jlf_hauling;
job_to_labor_table[df::job_type::StoreItemInHospital] = jlf_hauling;
job_to_labor_table[df::job_type::StoreItemInChest] = jlf_hauling;
job_to_labor_table[df::job_type::StoreItemInCabinet] = jlf_hauling;
job_to_labor_table[df::job_type::StoreWeapon] = jlf_hauling;
job_to_labor_table[df::job_type::StoreArmor] = jlf_hauling;
job_to_labor_table[df::job_type::StoreItemInBarrel] = jlf_hauling;
job_to_labor_table[df::job_type::StoreItemInBin] = jlf_const(df::unit_labor::HAUL_ITEM);
job_to_labor_table[df::job_type::SeekArtifact] = jlf_no_labor;
job_to_labor_table[df::job_type::SeekInfant] = jlf_no_labor;
job_to_labor_table[df::job_type::AttendParty] = jlf_no_labor;
job_to_labor_table[df::job_type::GoShopping] = jlf_no_labor;
job_to_labor_table[df::job_type::GoShopping2] = jlf_no_labor;
job_to_labor_table[df::job_type::Clean] = jlf_const(df::unit_labor::CLEAN);
job_to_labor_table[df::job_type::Rest] = jlf_no_labor;
job_to_labor_table[df::job_type::PickupEquipment] = jlf_no_labor;
job_to_labor_table[df::job_type::DumpItem] = jlf_const(df::unit_labor::HAUL_REFUSE);
job_to_labor_table[df::job_type::StrangeMoodCrafter] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodJeweller] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodForge] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodMagmaForge] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodBrooding] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodFell] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodCarpenter] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodMason] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodBowyer] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodTanner] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodWeaver] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodBrooding] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodFell] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodCarpenter] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodMason] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodBowyer] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodTanner] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodWeaver] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodGlassmaker] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodMechanics] = jlf_no_labor;
job_to_labor_table[df::job_type::StrangeMoodMechanics] = jlf_no_labor;
job_to_labor_table[df::job_type::ConstructBuilding] = new jlfunc_construct_bld();
job_to_labor_table[df::job_type::ConstructDoor] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructFloodgate] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructBed] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructThrone] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructCoffin] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructTable] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructChest] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructBin] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructArmorStand] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructWeaponRack] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructCabinet] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructStatue] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructBlocks] = jlf_make_furniture;
job_to_labor_table[df::job_type::MakeRawGlass] = jlf_const(df::unit_labor::GLASSMAKER);
job_to_labor_table[df::job_type::MakeCrafts] = jlf_make_object;
job_to_labor_table[df::job_type::MintCoins] = jlf_const(df::unit_labor::METAL_CRAFT);
job_to_labor_table[df::job_type::CutGems] = jlf_const(df::unit_labor::CUT_GEM);
job_to_labor_table[df::job_type::CutGlass] = jlf_const(df::unit_labor::CUT_GEM);
job_to_labor_table[df::job_type::EncrustWithGems] = jlf_const(df::unit_labor::ENCRUST_GEM);
job_to_labor_table[df::job_type::EncrustWithGlass] = jlf_const(df::unit_labor::ENCRUST_GEM);
job_to_labor_table[df::job_type::DestroyBuilding] = new jlfunc_destroy_bld();
job_to_labor_table[df::job_type::SmeltOre] = jlf_const(df::unit_labor::SMELT);
job_to_labor_table[df::job_type::MeltMetalObject] = jlf_const(df::unit_labor::SMELT);
job_to_labor_table[df::job_type::ExtractMetalStrands] = jlf_const(df::unit_labor::EXTRACT_STRAND);
job_to_labor_table[df::job_type::PlantSeeds] = jlf_const(df::unit_labor::PLANT);
job_to_labor_table[df::job_type::HarvestPlants] = jlf_const(df::unit_labor::PLANT);
job_to_labor_table[df::job_type::TrainHuntingAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN);
job_to_labor_table[df::job_type::TrainWarAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN);
job_to_labor_table[df::job_type::MakeWeapon] = jlf_make_weapon;
job_to_labor_table[df::job_type::ForgeAnvil] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructDoor] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructFloodgate] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructBed] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructThrone] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructCoffin] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructTable] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructChest] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructBin] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructArmorStand] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructWeaponRack] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructCabinet] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructStatue] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructBlocks] = jlf_make_furniture;
job_to_labor_table[df::job_type::MakeRawGlass] = jlf_const(df::unit_labor::GLASSMAKER);
job_to_labor_table[df::job_type::MakeCrafts] = jlf_make_object;
job_to_labor_table[df::job_type::MintCoins] = jlf_const(df::unit_labor::METAL_CRAFT);
job_to_labor_table[df::job_type::CutGems] = jlf_const(df::unit_labor::CUT_GEM);
job_to_labor_table[df::job_type::CutGlass] = jlf_const(df::unit_labor::CUT_GEM);
job_to_labor_table[df::job_type::EncrustWithGems] = jlf_const(df::unit_labor::ENCRUST_GEM);
job_to_labor_table[df::job_type::EncrustWithGlass] = jlf_const(df::unit_labor::ENCRUST_GEM);
job_to_labor_table[df::job_type::DestroyBuilding] = new jlfunc_destroy_bld();
job_to_labor_table[df::job_type::SmeltOre] = jlf_const(df::unit_labor::SMELT);
job_to_labor_table[df::job_type::MeltMetalObject] = jlf_const(df::unit_labor::SMELT);
job_to_labor_table[df::job_type::ExtractMetalStrands] = jlf_const(df::unit_labor::EXTRACT_STRAND);
job_to_labor_table[df::job_type::PlantSeeds] = jlf_const(df::unit_labor::PLANT);
job_to_labor_table[df::job_type::HarvestPlants] = jlf_const(df::unit_labor::PLANT);
job_to_labor_table[df::job_type::TrainHuntingAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN);
job_to_labor_table[df::job_type::TrainWarAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN);
job_to_labor_table[df::job_type::MakeWeapon] = jlf_make_weapon;
job_to_labor_table[df::job_type::ForgeAnvil] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructCatapultParts] = jlf_const(df::unit_labor::SIEGECRAFT);
job_to_labor_table[df::job_type::ConstructBallistaParts] = jlf_const(df::unit_labor::SIEGECRAFT);
job_to_labor_table[df::job_type::MakeArmor] = jlf_make_armor;
job_to_labor_table[df::job_type::MakeHelm] = jlf_make_armor;
job_to_labor_table[df::job_type::MakePants] = jlf_make_armor;
job_to_labor_table[df::job_type::StudWith] = jlf_make_object;
job_to_labor_table[df::job_type::ButcherAnimal] = jlf_const(df::unit_labor::BUTCHER);
job_to_labor_table[df::job_type::PrepareRawFish] = jlf_const(df::unit_labor::CLEAN_FISH);
job_to_labor_table[df::job_type::MillPlants] = jlf_const(df::unit_labor::MILLER);
job_to_labor_table[df::job_type::BaitTrap] = jlf_const(df::unit_labor::TRAPPER);
job_to_labor_table[df::job_type::MilkCreature] = jlf_const(df::unit_labor::MILK);
job_to_labor_table[df::job_type::MakeCheese] = jlf_const(df::unit_labor::MAKE_CHEESE);
job_to_labor_table[df::job_type::ProcessPlants] = jlf_const(df::unit_labor::PROCESS_PLANT);
job_to_labor_table[df::job_type::ProcessPlantsBag] = jlf_const(df::unit_labor::PROCESS_PLANT);
job_to_labor_table[df::job_type::ProcessPlantsVial] = jlf_const(df::unit_labor::PROCESS_PLANT);
job_to_labor_table[df::job_type::ProcessPlantsBarrel] = jlf_const(df::unit_labor::PROCESS_PLANT);
job_to_labor_table[df::job_type::PrepareMeal] = jlf_const(df::unit_labor::COOK);
job_to_labor_table[df::job_type::WeaveCloth] = jlf_const(df::unit_labor::WEAVER);
job_to_labor_table[df::job_type::MakeGloves] = jlf_make_armor;
job_to_labor_table[df::job_type::MakeShoes] = jlf_make_armor;
job_to_labor_table[df::job_type::MakeShield] = jlf_make_armor;
job_to_labor_table[df::job_type::MakeCage] = jlf_make_furniture;
job_to_labor_table[df::job_type::MakeChain] = jlf_make_object;
job_to_labor_table[df::job_type::MakeFlask] = jlf_make_object;
job_to_labor_table[df::job_type::MakeGoblet] = jlf_make_object;
job_to_labor_table[df::job_type::MakeInstrument] = jlf_make_object;
job_to_labor_table[df::job_type::MakeToy] = jlf_make_object;
job_to_labor_table[df::job_type::MakeAnimalTrap] = jlf_const(df::unit_labor::TRAPPER);
job_to_labor_table[df::job_type::MakeBarrel] = jlf_make_furniture;
job_to_labor_table[df::job_type::MakeBucket] = jlf_make_furniture;
job_to_labor_table[df::job_type::MakeWindow] = jlf_make_furniture;
job_to_labor_table[df::job_type::MakeTotem] = jlf_const(df::unit_labor::BONE_CARVE);
job_to_labor_table[df::job_type::MakeAmmo] = jlf_make_weapon;
job_to_labor_table[df::job_type::DecorateWith] = jlf_make_object;
job_to_labor_table[df::job_type::MakeBackpack] = jlf_make_object;
job_to_labor_table[df::job_type::MakeQuiver] = jlf_make_armor;
job_to_labor_table[df::job_type::MakeArmor] = jlf_make_armor;
job_to_labor_table[df::job_type::MakeHelm] = jlf_make_armor;
job_to_labor_table[df::job_type::MakePants] = jlf_make_armor;
job_to_labor_table[df::job_type::StudWith] = jlf_make_object;
job_to_labor_table[df::job_type::ButcherAnimal] = jlf_const(df::unit_labor::BUTCHER);
job_to_labor_table[df::job_type::PrepareRawFish] = jlf_const(df::unit_labor::CLEAN_FISH);
job_to_labor_table[df::job_type::MillPlants] = jlf_const(df::unit_labor::MILLER);
job_to_labor_table[df::job_type::BaitTrap] = jlf_const(df::unit_labor::TRAPPER);
job_to_labor_table[df::job_type::MilkCreature] = jlf_const(df::unit_labor::MILK);
job_to_labor_table[df::job_type::MakeCheese] = jlf_const(df::unit_labor::MAKE_CHEESE);
job_to_labor_table[df::job_type::ProcessPlants] = jlf_const(df::unit_labor::PROCESS_PLANT);
job_to_labor_table[df::job_type::ProcessPlantsBag] = jlf_const(df::unit_labor::PROCESS_PLANT);
job_to_labor_table[df::job_type::ProcessPlantsVial] = jlf_const(df::unit_labor::PROCESS_PLANT);
job_to_labor_table[df::job_type::ProcessPlantsBarrel] = jlf_const(df::unit_labor::PROCESS_PLANT);
job_to_labor_table[df::job_type::PrepareMeal] = jlf_const(df::unit_labor::COOK);
job_to_labor_table[df::job_type::WeaveCloth] = jlf_const(df::unit_labor::WEAVER);
job_to_labor_table[df::job_type::MakeGloves] = jlf_make_armor;
job_to_labor_table[df::job_type::MakeShoes] = jlf_make_armor;
job_to_labor_table[df::job_type::MakeShield] = jlf_make_armor;
job_to_labor_table[df::job_type::MakeCage] = jlf_make_furniture;
job_to_labor_table[df::job_type::MakeChain] = jlf_make_object;
job_to_labor_table[df::job_type::MakeFlask] = jlf_make_object;
job_to_labor_table[df::job_type::MakeGoblet] = jlf_make_object;
job_to_labor_table[df::job_type::MakeInstrument] = jlf_make_object;
job_to_labor_table[df::job_type::MakeToy] = jlf_make_object;
job_to_labor_table[df::job_type::MakeAnimalTrap] = jlf_const(df::unit_labor::TRAPPER);
job_to_labor_table[df::job_type::MakeBarrel] = jlf_make_furniture;
job_to_labor_table[df::job_type::MakeBucket] = jlf_make_furniture;
job_to_labor_table[df::job_type::MakeWindow] = jlf_make_furniture;
job_to_labor_table[df::job_type::MakeTotem] = jlf_const(df::unit_labor::BONE_CARVE);
job_to_labor_table[df::job_type::MakeAmmo] = jlf_make_weapon;
job_to_labor_table[df::job_type::DecorateWith] = jlf_make_object;
job_to_labor_table[df::job_type::MakeBackpack] = jlf_make_object;
job_to_labor_table[df::job_type::MakeQuiver] = jlf_make_armor;
job_to_labor_table[df::job_type::MakeBallistaArrowHead] = jlf_make_weapon;
job_to_labor_table[df::job_type::AssembleSiegeAmmo] = jlf_const(df::unit_labor::SIEGECRAFT);
job_to_labor_table[df::job_type::LoadCatapult] = jlf_const(df::unit_labor::SIEGEOPERATE);
job_to_labor_table[df::job_type::LoadBallista] = jlf_const(df::unit_labor::SIEGEOPERATE);
job_to_labor_table[df::job_type::FireCatapult] = jlf_const(df::unit_labor::SIEGEOPERATE);
job_to_labor_table[df::job_type::FireBallista] = jlf_const(df::unit_labor::SIEGEOPERATE);
job_to_labor_table[df::job_type::ConstructMechanisms] = jlf_const(df::unit_labor::MECHANIC);
job_to_labor_table[df::job_type::MakeTrapComponent] = jlf_const(df::unit_labor::MECHANIC) ;
job_to_labor_table[df::job_type::LoadCageTrap] = jlf_const(df::unit_labor::MECHANIC) ;
job_to_labor_table[df::job_type::LoadStoneTrap] = jlf_const(df::unit_labor::MECHANIC) ;
job_to_labor_table[df::job_type::LoadWeaponTrap] = jlf_const(df::unit_labor::MECHANIC) ;
job_to_labor_table[df::job_type::CleanTrap] = jlf_const(df::unit_labor::MECHANIC) ;
job_to_labor_table[df::job_type::CastSpell] = jlf_no_labor;
job_to_labor_table[df::job_type::AssembleSiegeAmmo] = jlf_const(df::unit_labor::SIEGECRAFT);
job_to_labor_table[df::job_type::LoadCatapult] = jlf_const(df::unit_labor::SIEGEOPERATE);
job_to_labor_table[df::job_type::LoadBallista] = jlf_const(df::unit_labor::SIEGEOPERATE);
job_to_labor_table[df::job_type::FireCatapult] = jlf_const(df::unit_labor::SIEGEOPERATE);
job_to_labor_table[df::job_type::FireBallista] = jlf_const(df::unit_labor::SIEGEOPERATE);
job_to_labor_table[df::job_type::ConstructMechanisms] = jlf_const(df::unit_labor::MECHANIC);
job_to_labor_table[df::job_type::MakeTrapComponent] = jlf_const(df::unit_labor::MECHANIC) ;
job_to_labor_table[df::job_type::LoadCageTrap] = jlf_const(df::unit_labor::MECHANIC) ;
job_to_labor_table[df::job_type::LoadStoneTrap] = jlf_const(df::unit_labor::MECHANIC) ;
job_to_labor_table[df::job_type::LoadWeaponTrap] = jlf_const(df::unit_labor::MECHANIC) ;
job_to_labor_table[df::job_type::CleanTrap] = jlf_const(df::unit_labor::MECHANIC) ;
job_to_labor_table[df::job_type::CastSpell] = jlf_no_labor;
job_to_labor_table[df::job_type::LinkBuildingToTrigger] = jlf_const(df::unit_labor::MECHANIC) ;
job_to_labor_table[df::job_type::PullLever] = jlf_no_labor;
job_to_labor_table[df::job_type::BrewDrink] = jlf_const(df::unit_labor::BREWER) ;
job_to_labor_table[df::job_type::ExtractFromPlants] = jlf_const(df::unit_labor::HERBALIST) ;
job_to_labor_table[df::job_type::ExtractFromRawFish] = jlf_const(df::unit_labor::DISSECT_FISH) ;
job_to_labor_table[df::job_type::PullLever] = jlf_no_labor;
job_to_labor_table[df::job_type::BrewDrink] = jlf_const(df::unit_labor::BREWER) ;
job_to_labor_table[df::job_type::ExtractFromPlants] = jlf_const(df::unit_labor::HERBALIST) ;
job_to_labor_table[df::job_type::ExtractFromRawFish] = jlf_const(df::unit_labor::DISSECT_FISH) ;
job_to_labor_table[df::job_type::ExtractFromLandAnimal] = jlf_const(df::unit_labor::DISSECT_VERMIN) ;
job_to_labor_table[df::job_type::TameVermin] = jlf_const(df::unit_labor::ANIMALTRAIN) ;
job_to_labor_table[df::job_type::TameAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN) ;
job_to_labor_table[df::job_type::ChainAnimal] = jlf_no_labor;
job_to_labor_table[df::job_type::UnchainAnimal] = jlf_no_labor;
job_to_labor_table[df::job_type::UnchainPet] = jlf_no_labor;
job_to_labor_table[df::job_type::ReleaseLargeCreature] = jlf_no_labor;
job_to_labor_table[df::job_type::ReleasePet] = jlf_no_labor;
job_to_labor_table[df::job_type::ReleaseSmallCreature] = jlf_no_labor;
job_to_labor_table[df::job_type::HandleSmallCreature] = jlf_no_labor;
job_to_labor_table[df::job_type::HandleLargeCreature] = jlf_no_labor;
job_to_labor_table[df::job_type::CageLargeCreature] = jlf_no_labor;
job_to_labor_table[df::job_type::CageSmallCreature] = jlf_no_labor;
job_to_labor_table[df::job_type::RecoverWounded] = jlf_const(df::unit_labor::RECOVER_WOUNDED);
job_to_labor_table[df::job_type::DiagnosePatient] = jlf_const(df::unit_labor::DIAGNOSE) ;
job_to_labor_table[df::job_type::ImmobilizeBreak] = jlf_const(df::unit_labor::BONE_SETTING) ;
job_to_labor_table[df::job_type::DressWound] = jlf_const(df::unit_labor::DRESSING_WOUNDS) ;
job_to_labor_table[df::job_type::CleanPatient] = jlf_const(df::unit_labor::DRESSING_WOUNDS) ;
job_to_labor_table[df::job_type::Surgery] = jlf_const(df::unit_labor::SURGERY) ;
job_to_labor_table[df::job_type::Suture] = jlf_const(df::unit_labor::SUTURING);
job_to_labor_table[df::job_type::SetBone] = jlf_const(df::unit_labor::BONE_SETTING) ;
job_to_labor_table[df::job_type::PlaceInTraction] = jlf_const(df::unit_labor::BONE_SETTING) ;
job_to_labor_table[df::job_type::DrainAquarium] = jlf_no_labor;
job_to_labor_table[df::job_type::FillAquarium] = jlf_no_labor;
job_to_labor_table[df::job_type::FillPond] = jlf_no_labor;
job_to_labor_table[df::job_type::GiveWater] = jlf_const(df::unit_labor::FEED_WATER_CIVILIANS) ;
job_to_labor_table[df::job_type::GiveFood] = jlf_const(df::unit_labor::FEED_WATER_CIVILIANS) ;
job_to_labor_table[df::job_type::GiveWater2] = jlf_no_labor;
job_to_labor_table[df::job_type::GiveFood2] = jlf_no_labor;
job_to_labor_table[df::job_type::RecoverPet] = jlf_no_labor;
job_to_labor_table[df::job_type::PitLargeAnimal] = jlf_no_labor;
job_to_labor_table[df::job_type::PitSmallAnimal] = jlf_no_labor;
job_to_labor_table[df::job_type::SlaughterAnimal] = jlf_const(df::unit_labor::BUTCHER);
job_to_labor_table[df::job_type::MakeCharcoal] = jlf_const(df::unit_labor::BURN_WOOD);
job_to_labor_table[df::job_type::MakeAsh] = jlf_const(df::unit_labor::BURN_WOOD);
job_to_labor_table[df::job_type::MakeLye] = jlf_const(df::unit_labor::LYE_MAKING);
job_to_labor_table[df::job_type::MakePotashFromLye] = jlf_const(df::unit_labor::POTASH_MAKING);
job_to_labor_table[df::job_type::FertilizeField] = jlf_const(df::unit_labor::PLANT);
job_to_labor_table[df::job_type::MakePotashFromAsh] = jlf_const(df::unit_labor::POTASH_MAKING);
job_to_labor_table[df::job_type::DyeThread] = jlf_const(df::unit_labor::DYER);
job_to_labor_table[df::job_type::DyeCloth] = jlf_const(df::unit_labor::DYER);
job_to_labor_table[df::job_type::SewImage] = jlf_make_object;
job_to_labor_table[df::job_type::MakePipeSection] = jlf_make_furniture;
job_to_labor_table[df::job_type::OperatePump] = jlf_const(df::unit_labor::OPERATE_PUMP);
job_to_labor_table[df::job_type::ManageWorkOrders] = jlf_no_labor;
job_to_labor_table[df::job_type::TameVermin] = jlf_const(df::unit_labor::ANIMALTRAIN) ;
job_to_labor_table[df::job_type::TameAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN) ;
job_to_labor_table[df::job_type::ChainAnimal] = jlf_no_labor;
job_to_labor_table[df::job_type::UnchainAnimal] = jlf_no_labor;
job_to_labor_table[df::job_type::UnchainPet] = jlf_no_labor;
job_to_labor_table[df::job_type::ReleaseLargeCreature] = jlf_no_labor;
job_to_labor_table[df::job_type::ReleasePet] = jlf_no_labor;
job_to_labor_table[df::job_type::ReleaseSmallCreature] = jlf_no_labor;
job_to_labor_table[df::job_type::HandleSmallCreature] = jlf_no_labor;
job_to_labor_table[df::job_type::HandleLargeCreature] = jlf_no_labor;
job_to_labor_table[df::job_type::CageLargeCreature] = jlf_no_labor;
job_to_labor_table[df::job_type::CageSmallCreature] = jlf_no_labor;
job_to_labor_table[df::job_type::RecoverWounded] = jlf_const(df::unit_labor::RECOVER_WOUNDED);
job_to_labor_table[df::job_type::DiagnosePatient] = jlf_const(df::unit_labor::DIAGNOSE) ;
job_to_labor_table[df::job_type::ImmobilizeBreak] = jlf_const(df::unit_labor::BONE_SETTING) ;
job_to_labor_table[df::job_type::DressWound] = jlf_const(df::unit_labor::DRESSING_WOUNDS) ;
job_to_labor_table[df::job_type::CleanPatient] = jlf_const(df::unit_labor::DRESSING_WOUNDS) ;
job_to_labor_table[df::job_type::Surgery] = jlf_const(df::unit_labor::SURGERY) ;
job_to_labor_table[df::job_type::Suture] = jlf_const(df::unit_labor::SUTURING);
job_to_labor_table[df::job_type::SetBone] = jlf_const(df::unit_labor::BONE_SETTING) ;
job_to_labor_table[df::job_type::PlaceInTraction] = jlf_const(df::unit_labor::BONE_SETTING) ;
job_to_labor_table[df::job_type::DrainAquarium] = jlf_no_labor;
job_to_labor_table[df::job_type::FillAquarium] = jlf_no_labor;
job_to_labor_table[df::job_type::FillPond] = jlf_no_labor;
job_to_labor_table[df::job_type::GiveWater] = jlf_const(df::unit_labor::FEED_WATER_CIVILIANS) ;
job_to_labor_table[df::job_type::GiveFood] = jlf_const(df::unit_labor::FEED_WATER_CIVILIANS) ;
job_to_labor_table[df::job_type::GiveWater2] = jlf_no_labor;
job_to_labor_table[df::job_type::GiveFood2] = jlf_no_labor;
job_to_labor_table[df::job_type::RecoverPet] = jlf_no_labor;
job_to_labor_table[df::job_type::PitLargeAnimal] = jlf_no_labor;
job_to_labor_table[df::job_type::PitSmallAnimal] = jlf_no_labor;
job_to_labor_table[df::job_type::SlaughterAnimal] = jlf_const(df::unit_labor::BUTCHER);
job_to_labor_table[df::job_type::MakeCharcoal] = jlf_const(df::unit_labor::BURN_WOOD);
job_to_labor_table[df::job_type::MakeAsh] = jlf_const(df::unit_labor::BURN_WOOD);
job_to_labor_table[df::job_type::MakeLye] = jlf_const(df::unit_labor::LYE_MAKING);
job_to_labor_table[df::job_type::MakePotashFromLye] = jlf_const(df::unit_labor::POTASH_MAKING);
job_to_labor_table[df::job_type::FertilizeField] = jlf_const(df::unit_labor::PLANT);
job_to_labor_table[df::job_type::MakePotashFromAsh] = jlf_const(df::unit_labor::POTASH_MAKING);
job_to_labor_table[df::job_type::DyeThread] = jlf_const(df::unit_labor::DYER);
job_to_labor_table[df::job_type::DyeCloth] = jlf_const(df::unit_labor::DYER);
job_to_labor_table[df::job_type::SewImage] = jlf_make_object;
job_to_labor_table[df::job_type::MakePipeSection] = jlf_make_furniture;
job_to_labor_table[df::job_type::OperatePump] = jlf_const(df::unit_labor::OPERATE_PUMP);
job_to_labor_table[df::job_type::ManageWorkOrders] = jlf_no_labor;
job_to_labor_table[df::job_type::UpdateStockpileRecords] = jlf_no_labor;
job_to_labor_table[df::job_type::TradeAtDepot] = jlf_no_labor;
job_to_labor_table[df::job_type::ConstructHatchCover] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructGrate] = jlf_make_furniture;
job_to_labor_table[df::job_type::RemoveStairs] = jlf_const(df::unit_labor::MINE);
job_to_labor_table[df::job_type::ConstructQuern] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructMillstone] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructSplint] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructCrutch] = jlf_make_furniture;
job_to_labor_table[df::job_type::TradeAtDepot] = jlf_no_labor;
job_to_labor_table[df::job_type::ConstructHatchCover] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructGrate] = jlf_make_furniture;
job_to_labor_table[df::job_type::RemoveStairs] = jlf_const(df::unit_labor::MINE);
job_to_labor_table[df::job_type::ConstructQuern] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructMillstone] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructSplint] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructCrutch] = jlf_make_furniture;
job_to_labor_table[df::job_type::ConstructTractionBench] = jlf_const(df::unit_labor::MECHANIC);
job_to_labor_table[df::job_type::CleanSelf] = jlf_no_labor;
job_to_labor_table[df::job_type::BringCrutch] = jlf_const(df::unit_labor::BONE_SETTING);
job_to_labor_table[df::job_type::ApplyCast] = jlf_const(df::unit_labor::BONE_SETTING);
job_to_labor_table[df::job_type::CleanSelf] = jlf_no_labor;
job_to_labor_table[df::job_type::BringCrutch] = jlf_const(df::unit_labor::BONE_SETTING);
job_to_labor_table[df::job_type::ApplyCast] = jlf_const(df::unit_labor::BONE_SETTING);
job_to_labor_table[df::job_type::CustomReaction] = new jlfunc_custom();
job_to_labor_table[df::job_type::ConstructSlab] = jlf_make_furniture;
job_to_labor_table[df::job_type::EngraveSlab] = jlf_const(df::unit_labor::DETAIL);
job_to_labor_table[df::job_type::ShearCreature] = jlf_const(df::unit_labor::SHEARER);
job_to_labor_table[df::job_type::SpinThread] = jlf_const(df::unit_labor::SPINNER);
job_to_labor_table[df::job_type::PenLargeAnimal] = jlf_no_labor;
job_to_labor_table[df::job_type::PenSmallAnimal] = jlf_no_labor;
job_to_labor_table[df::job_type::MakeTool] = jlf_make_furniture;
job_to_labor_table[df::job_type::CollectClay] = jlf_const(df::unit_labor::POTTERY);
job_to_labor_table[df::job_type::InstallColonyInHive] = jlf_const(df::unit_labor::BEEKEEPING);
job_to_labor_table[df::job_type::CollectHiveProducts] = jlf_const(df::unit_labor::BEEKEEPING);
job_to_labor_table[df::job_type::CauseTrouble] = jlf_no_labor;
job_to_labor_table[df::job_type::DrinkBlood] = jlf_no_labor;
job_to_labor_table[df::job_type::ReportCrime] = jlf_no_labor;
job_to_labor_table[df::job_type::ExecuteCriminal] = jlf_no_labor;
job_to_labor_table[df::job_type::TrainAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN);
job_to_labor_table[df::job_type::CarveTrack] = jlf_const(df::unit_labor::DETAIL);
job_to_labor_table[df::job_type::PushTrackVehicle] = jlf_const(df::unit_labor::PUSH_HAUL_VEHICLE);
job_to_labor_table[df::job_type::PlaceTrackVehicle] = jlf_const(df::unit_labor::PUSH_HAUL_VEHICLE);
job_to_labor_table[df::job_type::ConstructSlab] = jlf_make_furniture;
job_to_labor_table[df::job_type::EngraveSlab] = jlf_const(df::unit_labor::DETAIL);
job_to_labor_table[df::job_type::ShearCreature] = jlf_const(df::unit_labor::SHEARER);
job_to_labor_table[df::job_type::SpinThread] = jlf_const(df::unit_labor::SPINNER);
job_to_labor_table[df::job_type::PenLargeAnimal] = jlf_no_labor;
job_to_labor_table[df::job_type::PenSmallAnimal] = jlf_no_labor;
job_to_labor_table[df::job_type::MakeTool] = jlf_make_furniture;
job_to_labor_table[df::job_type::CollectClay] = jlf_const(df::unit_labor::POTTERY);
job_to_labor_table[df::job_type::InstallColonyInHive] = jlf_const(df::unit_labor::BEEKEEPING);
job_to_labor_table[df::job_type::CollectHiveProducts] = jlf_const(df::unit_labor::BEEKEEPING);
job_to_labor_table[df::job_type::CauseTrouble] = jlf_no_labor;
job_to_labor_table[df::job_type::DrinkBlood] = jlf_no_labor;
job_to_labor_table[df::job_type::ReportCrime] = jlf_no_labor;
job_to_labor_table[df::job_type::ExecuteCriminal] = jlf_no_labor;
job_to_labor_table[df::job_type::TrainAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN);
job_to_labor_table[df::job_type::CarveTrack] = jlf_const(df::unit_labor::DETAIL);
job_to_labor_table[df::job_type::PushTrackVehicle] = jlf_const(df::unit_labor::PUSH_HAUL_VEHICLE);
job_to_labor_table[df::job_type::PlaceTrackVehicle] = jlf_const(df::unit_labor::PUSH_HAUL_VEHICLE);
job_to_labor_table[df::job_type::StoreItemInVehicle] = jlf_const(df::unit_labor::PUSH_HAUL_VEHICLE);
};
@ -1505,7 +1505,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
" disables labors. Generally, each dwarf will be assigned exactly one labor.\n"
" Warning: autolabor will override any manual changes you make to labors\n"
" while it is enabled. Do not try to run both autolabor and autolabor2 at\n"
" the same time."
" the same time."
));
generate_labor_to_skill_map();
@ -1956,7 +1956,7 @@ private:
df::job_skill skill = labor_to_skill[labor];
if (skill != df::job_skill::NONE)
{
int skill_level = Units::getNominalSkill(dwarf->dwarf, skill, false);
int skill_level = Units::getNominalSkill(dwarf->dwarf, skill, false);
high_skill = std::max(high_skill, skill_level);
}
}
@ -2067,7 +2067,7 @@ public:
// add job entries for health care
labor_needed[df::unit_labor::RECOVER_WOUNDED] += cnt_recover_wounded;
labor_needed[df::unit_labor::DIAGNOSE] += cnt_diagnosis;
labor_needed[df::unit_labor::DIAGNOSE] += cnt_diagnosis;
labor_needed[df::unit_labor::BONE_SETTING] += cnt_immobilize;
labor_needed[df::unit_labor::DRESSING_WOUNDS] += cnt_dressing;
labor_needed[df::unit_labor::DRESSING_WOUNDS] += cnt_cleaning;

@ -1 +1 @@
Subproject commit a80abe848e4886a210e7a5123192e9221dc85810
Subproject commit 5b167d2ba89b877d80e0609feae8771aeaef356d

@ -71,14 +71,14 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
" L: Low Traffic\n"
" R: Restricted Traffic\n"
));
commands.push_back(PluginCommand(
"restrictliquids","Restrict on every visible square with liquid",
restrictLiquid, false, ""
));
commands.push_back(PluginCommand(
"restrictice","Restrict traffic on squares above visible ice",
restrictIce, false, ""
));
commands.push_back(PluginCommand(
"restrictliquids","Restrict on every visible square with liquid",
restrictLiquid, false, ""
));
commands.push_back(PluginCommand(
"restrictice","Restrict traffic on squares above visible ice",
restrictIce, false, ""
));
return CR_OK;
}
@ -285,7 +285,7 @@ command_result restrictLiquid(color_ostream &out, std::vector<std::string> & par
command_result restrictIce(color_ostream &out, std::vector<std::string> & params)
{
return setAllMatching(out, restrictIceProc);
return setAllMatching(out, restrictIceProc);
}
//Helper function for writing new functions that check every tile on the map.
@ -383,29 +383,29 @@ void allRestricted(DFCoord coord, MapExtras::MapCache &map)
//Restrict traffic if tile is visible and liquid is present.
void restrictLiquidProc(DFCoord coord, MapExtras::MapCache &map)
{
df::tile_designation des = map.designationAt(coord);
if ((des.bits.hidden == 0) && (des.bits.flow_size != 0))
{
des.bits.traffic = tile_traffic::Restricted;
map.setDesignationAt(coord, des);
}
df::tile_designation des = map.designationAt(coord);
if ((des.bits.hidden == 0) && (des.bits.flow_size != 0))
{
des.bits.traffic = tile_traffic::Restricted;
map.setDesignationAt(coord, des);
}
}
//Restrict traffice if tile is above visible ice wall.
void restrictIceProc(DFCoord coord, MapExtras::MapCache &map)
{
//There is no ice below the bottom of the map.
if (coord.z == 0)
return;
DFCoord tile_below = DFCoord(coord.x, coord.y, coord.z - 1);
df::tiletype tt = map.tiletypeAt(tile_below);
df::tile_designation des = map.designationAt(tile_below);
if ((des.bits.hidden == 0) && (tileMaterial(tt) == tiletype_material::FROZEN_LIQUID))
{
des = map.designationAt(coord);
des.bits.traffic = tile_traffic::Restricted;
map.setDesignationAt(coord, des);
}
//There is no ice below the bottom of the map.
if (coord.z == 0)
return;
DFCoord tile_below = DFCoord(coord.x, coord.y, coord.z - 1);
df::tiletype tt = map.tiletypeAt(tile_below);
df::tile_designation des = map.designationAt(tile_below);
if ((des.bits.hidden == 0) && (tileMaterial(tt) == tiletype_material::FROZEN_LIQUID))
{
des = map.designationAt(coord);
des.bits.traffic = tile_traffic::Restricted;
map.setDesignationAt(coord, des);
}
}

@ -9,30 +9,30 @@ DFHACK_PLUGIN("fortplan");
command_result fortplan(color_ostream &out, vector<string> & params);
struct BuildingInfo {
std::string code;
df::building_type type;
df::furnace_type furnaceType;
df::workshop_type workshopType;
df::trap_type trapType;
std::string name;
bool variableSize;
int defaultHeight;
int defaultWidth;
bool hasCustomOptions;
BuildingInfo(std::string theCode, df::building_type theType, std::string theName, int height, int width) {
code = theCode;
type = theType;
name = theName;
variableSize = false;
defaultHeight = height;
defaultWidth = width;
hasCustomOptions = false;
}
bool allocate() {
return planner.allocatePlannedBuilding(type);
}
std::string code;
df::building_type type;
df::furnace_type furnaceType;
df::workshop_type workshopType;
df::trap_type trapType;
std::string name;
bool variableSize;
int defaultHeight;
int defaultWidth;
bool hasCustomOptions;
BuildingInfo(std::string theCode, df::building_type theType, std::string theName, int height, int width) {
code = theCode;
type = theType;
name = theName;
variableSize = false;
defaultHeight = height;
defaultWidth = width;
hasCustomOptions = false;
}
bool allocate() {
return planner.allocatePlannedBuilding(type);
}
};
class MatchesCode
@ -55,32 +55,32 @@ DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCom
"Lay out buildings in your fortress based on a Quickfort-style CSV input file.\n"
"Usage: fortplan [filename]\n"));
buildings.push_back(BuildingInfo("c",df::building_type::Chair,"Chair",1,1));
buildings.push_back(BuildingInfo("b",df::building_type::Bed,"Bed",1,1));
buildings.push_back(BuildingInfo("t",df::building_type::Table,"Table",1,1));
buildings.push_back(BuildingInfo("n",df::building_type::Coffin,"Coffin",1,1));
buildings.push_back(BuildingInfo("d",df::building_type::Door,"Door",1,1));
buildings.push_back(BuildingInfo("x",df::building_type::Floodgate,"Floodgate",1,1));
buildings.push_back(BuildingInfo("h",df::building_type::Box,"Box",1,1));
buildings.push_back(BuildingInfo("r",df::building_type::Weaponrack,"Weapon Rack",1,1));
buildings.push_back(BuildingInfo("c",df::building_type::Chair,"Chair",1,1));
buildings.push_back(BuildingInfo("b",df::building_type::Bed,"Bed",1,1));
buildings.push_back(BuildingInfo("t",df::building_type::Table,"Table",1,1));
buildings.push_back(BuildingInfo("n",df::building_type::Coffin,"Coffin",1,1));
buildings.push_back(BuildingInfo("d",df::building_type::Door,"Door",1,1));
buildings.push_back(BuildingInfo("x",df::building_type::Floodgate,"Floodgate",1,1));
buildings.push_back(BuildingInfo("h",df::building_type::Box,"Box",1,1));
buildings.push_back(BuildingInfo("r",df::building_type::Weaponrack,"Weapon Rack",1,1));
buildings.push_back(BuildingInfo("a",df::building_type::Armorstand,"Armor Stand",1,1));
buildings.push_back(BuildingInfo("f",df::building_type::Cabinet,"Cabinet",1,1));
buildings.push_back(BuildingInfo("s",df::building_type::Statue,"Statue",1,1));
buildings.push_back(BuildingInfo("y",df::building_type::WindowGlass,"Glass Window",1,1));
buildings.push_back(BuildingInfo("m",df::building_type::AnimalTrap,"Animal Trap",1,1));
buildings.push_back(BuildingInfo("v",df::building_type::Chain,"Chain",1,1));
buildings.push_back(BuildingInfo("j",df::building_type::Cage,"Cage",1,1));
buildings.push_back(BuildingInfo("H",df::building_type::Hatch,"Floor Hatch",1,1));
buildings.push_back(BuildingInfo("W",df::building_type::GrateWall,"Wall Grate",1,1));
buildings.push_back(BuildingInfo("G",df::building_type::GrateFloor,"Floor Grate",1,1));
buildings.push_back(BuildingInfo("B",df::building_type::BarsVertical,"Vertical Bars",1,1));
buildings.push_back(BuildingInfo("~b",df::building_type::BarsFloor,"Floor Bars",1,1));
buildings.push_back(BuildingInfo("R",df::building_type::TractionBench,"Traction Bench",1,1));
buildings.push_back(BuildingInfo("~s",df::building_type::Slab,"Slab",1,1));
buildings.push_back(BuildingInfo("N",df::building_type::NestBox,"Nest Box",1,1));
buildings.push_back(BuildingInfo("~h",df::building_type::Hive,"Hive",1,1));
planner.initialize();
buildings.push_back(BuildingInfo("f",df::building_type::Cabinet,"Cabinet",1,1));
buildings.push_back(BuildingInfo("s",df::building_type::Statue,"Statue",1,1));
buildings.push_back(BuildingInfo("y",df::building_type::WindowGlass,"Glass Window",1,1));
buildings.push_back(BuildingInfo("m",df::building_type::AnimalTrap,"Animal Trap",1,1));
buildings.push_back(BuildingInfo("v",df::building_type::Chain,"Chain",1,1));
buildings.push_back(BuildingInfo("j",df::building_type::Cage,"Cage",1,1));
buildings.push_back(BuildingInfo("H",df::building_type::Hatch,"Floor Hatch",1,1));
buildings.push_back(BuildingInfo("W",df::building_type::GrateWall,"Wall Grate",1,1));
buildings.push_back(BuildingInfo("G",df::building_type::GrateFloor,"Floor Grate",1,1));
buildings.push_back(BuildingInfo("B",df::building_type::BarsVertical,"Vertical Bars",1,1));
buildings.push_back(BuildingInfo("~b",df::building_type::BarsFloor,"Floor Bars",1,1));
buildings.push_back(BuildingInfo("R",df::building_type::TractionBench,"Traction Bench",1,1));
buildings.push_back(BuildingInfo("~s",df::building_type::Slab,"Slab",1,1));
buildings.push_back(BuildingInfo("N",df::building_type::NestBox,"Nest Box",1,1));
buildings.push_back(BuildingInfo("~h",df::building_type::Hive,"Hive",1,1));
planner.initialize();
return CR_OK;
}
@ -116,260 +116,260 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
}
std::vector<std::vector<std::string>> tokenizeFile(std::string filename) {
std::ifstream infile(filename.c_str());
std::vector<std::vector<std::string>> fileTokens(128, std::vector<std::string>(128));
std::vector<std::vector<std::string>>::size_type x, y;
if (!infile.good()) {
throw -1;
}
std::string line;
y = 0;
while (std::getline(infile, line)) {
x = 0;
if (strcmp(line.substr(0,1).c_str(),"#")==0) {
fileTokens[y++][0] = line;
continue;
}
int start = 0;
auto nextInd = line.find(',');
std::string curCell = line.substr(start,nextInd-start);
do {
fileTokens[y][x] = curCell;
start = nextInd+1;
nextInd = line.find(',',start);
curCell = line.substr(start,nextInd-start);
x++;
} while (nextInd != line.npos);
y++;
}
return fileTokens;
std::ifstream infile(filename.c_str());
std::vector<std::vector<std::string>> fileTokens(128, std::vector<std::string>(128));
std::vector<std::vector<std::string>>::size_type x, y;
if (!infile.good()) {
throw -1;
}
std::string line;
y = 0;
while (std::getline(infile, line)) {
x = 0;
if (strcmp(line.substr(0,1).c_str(),"#")==0) {
fileTokens[y++][0] = line;
continue;
}
int start = 0;
auto nextInd = line.find(',');
std::string curCell = line.substr(start,nextInd-start);
do {
fileTokens[y][x] = curCell;
start = nextInd+1;
nextInd = line.find(',',start);
curCell = line.substr(start,nextInd-start);
x++;
} while (nextInd != line.npos);
y++;
}
return fileTokens;
}
command_result fortplan(color_ostream &out, vector<string> & params) {
auto & con = out;
std::vector<std::vector<std::string>> layout(128, std::vector<std::string>(128));
if (params.size()) {
coord32_t cursor;
coord32_t userCursor;
coord32_t startCursor;
if (!DFHack::Gui::getCursorCoords(cursor.x, cursor.y, cursor.z)) {
con.print("You must have an active in-game cursor.\n");
return CR_FAILURE;
}
DFHack::Gui::getCursorCoords(startCursor.x, startCursor.y, startCursor.z);
userCursor = startCursor;
std::string cwd = Filesystem::getcwd();
std::string filename = cwd+"/"+params[0];
con.print("Loading file '%s'...\n",filename.c_str());
try {
layout = tokenizeFile(filename);
} catch (int e) {
con.print("Could not open the file.\n");
return CR_FAILURE;
}
if (!is_enabled) {
plugin_enable(out, true);
}
con.print("Loaded.\n");
std::vector<std::vector<std::string>>::size_type x, y;
bool started = false;
for (y = 0; y < layout.size(); y++) {
x = 0;
auto hashBuild = layout[y][x].find("#build");
if (hashBuild != layout[y][x].npos) {
auto startLoc = layout[y][x].find("start(");
if (startLoc != layout[y][x].npos) {
startLoc += 6;
auto nextDelimiter = layout[y][x].find(";",startLoc);
std::string startXStr = layout[y][x].substr(startLoc,nextDelimiter-startLoc);
int startXOffset = std::stoi(startXStr);
startLoc = nextDelimiter+1;
nextDelimiter = layout[y][x].find(";",startLoc);
std::string startYStr = layout[y][x].substr(startLoc,nextDelimiter-startLoc);
int startYOffset = std::stoi(startYStr);
startCursor.x -= startXOffset;
startCursor.y -= startYOffset;
DFHack::Gui::setCursorCoords(startCursor.x,startCursor.y,startCursor.z);
started = true;
auto startEnd = layout[y][x].find(")",nextDelimiter);
con.print("Starting at (%d,%d,%d) which is described as: %s\n",startCursor.x,startCursor.y,startCursor.z,layout[y][x].substr(nextDelimiter+1,startEnd-nextDelimiter).c_str());
std::string desc = layout[y][x].substr(startEnd+1);
if (desc.size()>0) {
con.print("Description of this plan: %s\n",desc.c_str());
}
continue;
} else {
con.print("No start location found for this block\n");
}
} else if (!started) {
con.print("Not a build file: %s\n",layout[y][x].c_str());
break;
}
for (x = 0; x < layout[y].size(); x++) {
if (strcmp(layout[y][x].substr(0,1).c_str(),"#")==0) {
continue;
}
if (strcmp(layout[y][x].c_str(),"`")!=0) {
auto dataIndex = layout[y][x].find("(");
std::string curCode;
std::vector<std::string> curData;
if (dataIndex != layout[y][x].npos) {
curCode = layout[y][x].substr(0,dataIndex);
int dataStart = dataIndex+1;
auto nextDataStart = layout[y][x].find(",",dataStart);
while (nextDataStart!=layout[y][x].npos) {
std::string nextData = layout[y][x].substr(dataStart,nextDataStart);
if (strcmp(nextData.substr(nextData.size()-1,1).c_str(),")")==0) {
nextData = nextData.substr(0,nextData.size()-1);
}
curData.push_back(nextData);
dataStart = nextDataStart+1;
nextDataStart = layout[y][x].find(",",dataStart);
}
} else {
curCode = layout[y][x];
}
//con.print("Found a cell with '%s' in it (layout[y][x] %d:%d-%d)\n",layout[y][x].c_str(),lineNum,start,nextInd);
auto buildingIndex = std::find_if(buildings.begin(), buildings.end(), MatchesCode(curCode.c_str()));
// = std::find(validInstructions.begin(), validInstructions.end(), layout[y][x]);
if(buildingIndex == buildings.end()) {
//con.print("That is not a valid code.\n");
} else {
//con.print("I can build that!\n");
BuildingInfo buildingInfo = *buildingIndex;
if (buildingInfo.variableSize || buildingInfo.defaultHeight > 1 || buildingInfo.defaultWidth > 1) {
//con.print("Found a building at (%d,%d) called %s, which has a size %dx%d or variable size\n",x,y,buildingInfo.name.c_str(),buildingInfo.defaultWidth, buildingInfo.defaultHeight);
// TODO: Make this function smarter, able to determine the exact shape
// and location of the building
// For now, we just assume that we are always looking at the top left
// corner of where it is located in the input file
coord32_t buildingSize;
if (!buildingInfo.variableSize) {
bool single = true;
bool block = true;
std::vector<std::vector<std::string>>::size_type checkX, checkY;
int yOffset = ((buildingInfo.defaultHeight-1)/2);
int xOffset = ((buildingInfo.defaultWidth-1)/2);
//con.print(" - Checking to see if it's a single, with %d<=x<%d and %d<=y<%d...\n",x-xOffset,x+xOffset,y-yOffset,y+yOffset);
// First, check to see if this is in the center of an empty square of its default size
for (checkY = y-yOffset; checkY <= (y+yOffset); checkY++) {
for (checkX = x-xOffset; checkX <= (x+xOffset); checkX++) {
if (checkX==x && checkY==y) {
continue;
}
auto checkDataIndex = layout[checkY][checkX].find("(");
std::string checkCode;
if (checkDataIndex != layout[checkY][checkX].npos) {
checkCode = layout[checkY][checkX].substr(0,checkDataIndex);
} else {
checkCode = layout[checkY][checkX];
}
con.print(" - Code at (%d,%d) is '%s': ",checkX,checkY,checkCode.c_str());
auto checkIndex = std::find_if(buildings.begin(), buildings.end(), MatchesCode(checkCode.c_str()));
//if (checkIndex == buildings.end()) {
// con.print("this is not a valid code, so we keep going.\n");
// continue;
//}
//if (curCode.compare(layout[checkY][checkX]) != 0) {
if (checkIndex != buildings.end()) {
//con.print("this is a building, so we break.\n");
single = false;
break;
} else {
//con.print("this is not a building, so we keep going.\n");
}
}
if (!single) {
//con.print("Not a single. Moving forward.\n");
break;
}
}
if (!single) {
// If that's not the case, check to see if this is the top-left corner of
// a square of its default size
//con.print(" - It's not single; checking to see if it's a block...\n");
for (checkY = y; checkY < (y+buildingInfo.defaultHeight); checkY++) {
for (checkX = x; checkX < (x+buildingInfo.defaultWidth); checkX++) {
if (checkX==x && checkY==y) {
continue;
}
auto checkDataIndex = layout[checkY][checkX].find("(");
std::string checkCode;
if (checkDataIndex != layout[checkY][checkX].npos) {
checkCode = layout[checkY][checkX].substr(0,checkDataIndex);
} else {
checkCode = layout[checkY][checkX];
}
//con.print(" - Code at (%d,%d) is '%s': ",checkX,checkY,checkCode.c_str());
if (curCode.compare(checkCode) != 0) {
//con.print("this is not the same as '%s', so we break.\n",curCode.c_str());
block = false;
break;
} else {
//con.print("this is the same as '%s', so we erase it and move on.\n",curCode.c_str());
layout[checkY][checkX] = "``";
}
}
if (!block) {
//con.print("Not a block. Moving forward.\n");
break;
}
}
}
if (single) {
//con.print("Placing a building with code '%s' centered at (%d,%d) and default size %dx%d.\n",curCode.c_str(),x,y,buildingInfo.defaultWidth,buildingInfo.defaultHeight);
coord32_t offsetCursor = cursor;
offsetCursor.x -= xOffset;
offsetCursor.y -= yOffset;
DFHack::Gui::setCursorCoords(offsetCursor.x, offsetCursor.y, offsetCursor.z);
if (!buildingInfo.allocate()) {
con.print("*** There was an error placing building with code '%s' centered at (%d,%d).\n",curCode.c_str(),x,y);
}
DFHack::Gui::setCursorCoords(cursor.x, cursor.y, cursor.z);
} else if (block) {
//con.print("Placing a building with code '%s' with corner at (%d,%d) and default size %dx%d.\n",curCode.c_str(),x,y,buildingInfo.defaultWidth,buildingInfo.defaultHeight);
if (!buildingInfo.allocate()) {
con.print("*** There was an error placing building with code '%s' with corner at (%d,%d).\n",curCode.c_str(),x,y);
}
} else {
con.print("*** Found a code '%s' at (%d,%d) for a building with default size %dx%d with an invalid size designation.\n",curCode.c_str(),x,y,buildingInfo.defaultWidth,buildingInfo.defaultHeight);
}
} else {
//buildingSize = findBuildingExtent(layout, x, y, -1, -1, out);
//con.print(" - The building has variable size %dx%d\n",buildingSize.x, buildingSize.y);
//con.print(" - The building has a variable size, which is not yet handled.\n");
}
} else {
//con.print("Building a(n) %s.\n",buildingInfo.name.c_str());
if (!buildingInfo.allocate()) {
con.print("*** There was an error placing the %s at (%d,%d).\n",buildingInfo.name.c_str(),x,y);
}
}
}
}
cursor.x++;
DFHack::Gui::setCursorCoords(cursor.x, cursor.y, cursor.z);
}
cursor.y++;
cursor.x = startCursor.x;
}
DFHack::Gui::setCursorCoords(userCursor.x, userCursor.y, userCursor.z);
con.print("Done with file.\n");
} else {
con.print("You must supply a filename to read.\n");
}
return CR_OK;
if (params.size()) {
coord32_t cursor;
coord32_t userCursor;
coord32_t startCursor;
if (!DFHack::Gui::getCursorCoords(cursor.x, cursor.y, cursor.z)) {
con.print("You must have an active in-game cursor.\n");
return CR_FAILURE;
}
DFHack::Gui::getCursorCoords(startCursor.x, startCursor.y, startCursor.z);
userCursor = startCursor;
std::string cwd = Filesystem::getcwd();
std::string filename = cwd+"/"+params[0];
con.print("Loading file '%s'...\n",filename.c_str());
try {
layout = tokenizeFile(filename);
} catch (int e) {
con.print("Could not open the file.\n");
return CR_FAILURE;
}
if (!is_enabled) {
plugin_enable(out, true);
}
con.print("Loaded.\n");
std::vector<std::vector<std::string>>::size_type x, y;
bool started = false;
for (y = 0; y < layout.size(); y++) {
x = 0;
auto hashBuild = layout[y][x].find("#build");
if (hashBuild != layout[y][x].npos) {
auto startLoc = layout[y][x].find("start(");
if (startLoc != layout[y][x].npos) {
startLoc += 6;
auto nextDelimiter = layout[y][x].find(";",startLoc);
std::string startXStr = layout[y][x].substr(startLoc,nextDelimiter-startLoc);
int startXOffset = std::stoi(startXStr);
startLoc = nextDelimiter+1;
nextDelimiter = layout[y][x].find(";",startLoc);
std::string startYStr = layout[y][x].substr(startLoc,nextDelimiter-startLoc);
int startYOffset = std::stoi(startYStr);
startCursor.x -= startXOffset;
startCursor.y -= startYOffset;
DFHack::Gui::setCursorCoords(startCursor.x,startCursor.y,startCursor.z);
started = true;
auto startEnd = layout[y][x].find(")",nextDelimiter);
con.print("Starting at (%d,%d,%d) which is described as: %s\n",startCursor.x,startCursor.y,startCursor.z,layout[y][x].substr(nextDelimiter+1,startEnd-nextDelimiter).c_str());
std::string desc = layout[y][x].substr(startEnd+1);
if (desc.size()>0) {
con.print("Description of this plan: %s\n",desc.c_str());
}
continue;
} else {
con.print("No start location found for this block\n");
}
} else if (!started) {
con.print("Not a build file: %s\n",layout[y][x].c_str());
break;
}
for (x = 0; x < layout[y].size(); x++) {
if (strcmp(layout[y][x].substr(0,1).c_str(),"#")==0) {
continue;
}
if (strcmp(layout[y][x].c_str(),"`")!=0) {
auto dataIndex = layout[y][x].find("(");
std::string curCode;
std::vector<std::string> curData;
if (dataIndex != layout[y][x].npos) {
curCode = layout[y][x].substr(0,dataIndex);
int dataStart = dataIndex+1;
auto nextDataStart = layout[y][x].find(",",dataStart);
while (nextDataStart!=layout[y][x].npos) {
std::string nextData = layout[y][x].substr(dataStart,nextDataStart);
if (strcmp(nextData.substr(nextData.size()-1,1).c_str(),")")==0) {
nextData = nextData.substr(0,nextData.size()-1);
}
curData.push_back(nextData);
dataStart = nextDataStart+1;
nextDataStart = layout[y][x].find(",",dataStart);
}
} else {
curCode = layout[y][x];
}
//con.print("Found a cell with '%s' in it (layout[y][x] %d:%d-%d)\n",layout[y][x].c_str(),lineNum,start,nextInd);
auto buildingIndex = std::find_if(buildings.begin(), buildings.end(), MatchesCode(curCode.c_str()));
// = std::find(validInstructions.begin(), validInstructions.end(), layout[y][x]);
if(buildingIndex == buildings.end()) {
//con.print("That is not a valid code.\n");
} else {
//con.print("I can build that!\n");
BuildingInfo buildingInfo = *buildingIndex;
if (buildingInfo.variableSize || buildingInfo.defaultHeight > 1 || buildingInfo.defaultWidth > 1) {
//con.print("Found a building at (%d,%d) called %s, which has a size %dx%d or variable size\n",x,y,buildingInfo.name.c_str(),buildingInfo.defaultWidth, buildingInfo.defaultHeight);
// TODO: Make this function smarter, able to determine the exact shape
// and location of the building
// For now, we just assume that we are always looking at the top left
// corner of where it is located in the input file
coord32_t buildingSize;
if (!buildingInfo.variableSize) {
bool single = true;
bool block = true;
std::vector<std::vector<std::string>>::size_type checkX, checkY;
int yOffset = ((buildingInfo.defaultHeight-1)/2);
int xOffset = ((buildingInfo.defaultWidth-1)/2);
//con.print(" - Checking to see if it's a single, with %d<=x<%d and %d<=y<%d...\n",x-xOffset,x+xOffset,y-yOffset,y+yOffset);
// First, check to see if this is in the center of an empty square of its default size
for (checkY = y-yOffset; checkY <= (y+yOffset); checkY++) {
for (checkX = x-xOffset; checkX <= (x+xOffset); checkX++) {
if (checkX==x && checkY==y) {
continue;
}
auto checkDataIndex = layout[checkY][checkX].find("(");
std::string checkCode;
if (checkDataIndex != layout[checkY][checkX].npos) {
checkCode = layout[checkY][checkX].substr(0,checkDataIndex);
} else {
checkCode = layout[checkY][checkX];
}
con.print(" - Code at (%d,%d) is '%s': ",checkX,checkY,checkCode.c_str());
auto checkIndex = std::find_if(buildings.begin(), buildings.end(), MatchesCode(checkCode.c_str()));
//if (checkIndex == buildings.end()) {
// con.print("this is not a valid code, so we keep going.\n");
// continue;
//}
//if (curCode.compare(layout[checkY][checkX]) != 0) {
if (checkIndex != buildings.end()) {
//con.print("this is a building, so we break.\n");
single = false;
break;
} else {
//con.print("this is not a building, so we keep going.\n");
}
}
if (!single) {
//con.print("Not a single. Moving forward.\n");
break;
}
}
if (!single) {
// If that's not the case, check to see if this is the top-left corner of
// a square of its default size
//con.print(" - It's not single; checking to see if it's a block...\n");
for (checkY = y; checkY < (y+buildingInfo.defaultHeight); checkY++) {
for (checkX = x; checkX < (x+buildingInfo.defaultWidth); checkX++) {
if (checkX==x && checkY==y) {
continue;
}
auto checkDataIndex = layout[checkY][checkX].find("(");
std::string checkCode;
if (checkDataIndex != layout[checkY][checkX].npos) {
checkCode = layout[checkY][checkX].substr(0,checkDataIndex);
} else {
checkCode = layout[checkY][checkX];
}
//con.print(" - Code at (%d,%d) is '%s': ",checkX,checkY,checkCode.c_str());
if (curCode.compare(checkCode) != 0) {
//con.print("this is not the same as '%s', so we break.\n",curCode.c_str());
block = false;
break;
} else {
//con.print("this is the same as '%s', so we erase it and move on.\n",curCode.c_str());
layout[checkY][checkX] = "``";
}
}
if (!block) {
//con.print("Not a block. Moving forward.\n");
break;
}
}
}
if (single) {
//con.print("Placing a building with code '%s' centered at (%d,%d) and default size %dx%d.\n",curCode.c_str(),x,y,buildingInfo.defaultWidth,buildingInfo.defaultHeight);
coord32_t offsetCursor = cursor;
offsetCursor.x -= xOffset;
offsetCursor.y -= yOffset;
DFHack::Gui::setCursorCoords(offsetCursor.x, offsetCursor.y, offsetCursor.z);
if (!buildingInfo.allocate()) {
con.print("*** There was an error placing building with code '%s' centered at (%d,%d).\n",curCode.c_str(),x,y);
}
DFHack::Gui::setCursorCoords(cursor.x, cursor.y, cursor.z);
} else if (block) {
//con.print("Placing a building with code '%s' with corner at (%d,%d) and default size %dx%d.\n",curCode.c_str(),x,y,buildingInfo.defaultWidth,buildingInfo.defaultHeight);
if (!buildingInfo.allocate()) {
con.print("*** There was an error placing building with code '%s' with corner at (%d,%d).\n",curCode.c_str(),x,y);
}
} else {
con.print("*** Found a code '%s' at (%d,%d) for a building with default size %dx%d with an invalid size designation.\n",curCode.c_str(),x,y,buildingInfo.defaultWidth,buildingInfo.defaultHeight);
}
} else {
//buildingSize = findBuildingExtent(layout, x, y, -1, -1, out);
//con.print(" - The building has variable size %dx%d\n",buildingSize.x, buildingSize.y);
//con.print(" - The building has a variable size, which is not yet handled.\n");
}
} else {
//con.print("Building a(n) %s.\n",buildingInfo.name.c_str());
if (!buildingInfo.allocate()) {
con.print("*** There was an error placing the %s at (%d,%d).\n",buildingInfo.name.c_str(),x,y);
}
}
}
}
cursor.x++;
DFHack::Gui::setCursorCoords(cursor.x, cursor.y, cursor.z);
}
cursor.y++;
cursor.x = startCursor.x;
}
DFHack::Gui::setCursorCoords(userCursor.x, userCursor.y, userCursor.z);
con.print("Done with file.\n");
} else {
con.print("You must supply a filename to read.\n");
}
return CR_OK;
}

@ -1 +1 @@
Subproject commit 07750ad7f7ce7c2506e5198ffb80ca50a73e9c4e
Subproject commit 85dcde97197bdde1c1e97ccb536f2cc4cab6818f

@ -130,39 +130,39 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
// CoreSuspender suspend;
// // Actually do something here. Yay.
// out.print("Doing a test...\n");
// MapExtras::MapCache MC;
// EmbarkTile test_tile;
// if(!gather_embark_tile(0,0, &test_tile, &MC))
// return CR_FAILURE;
// //test-write the file to check it.
// std::ofstream output_file("tile.p", std::ios_base::binary);
// output_file << test_tile.SerializeAsString();
// output_file.close();
// MapExtras::MapCache MC;
// EmbarkTile test_tile;
// if(!gather_embark_tile(0,0, &test_tile, &MC))
// return CR_FAILURE;
// //test-write the file to check it.
// std::ofstream output_file("tile.p", std::ios_base::binary);
// output_file << test_tile.SerializeAsString();
// output_file.close();
//
// //load it again to verify.
// std::ifstream input_file("tile.p", std::ios_base::binary);
// std::string input_string( (std::istreambuf_iterator<char>(input_file) ),
// //load it again to verify.
// std::ifstream input_file("tile.p", std::ios_base::binary);
// std::string input_string( (std::istreambuf_iterator<char>(input_file) ),
// (std::istreambuf_iterator<char>() ) );
// EmbarkTile verify_tile;
// verify_tile.ParseFromString(input_string);
// //write contents to text file.
// std::ofstream debug_text("tile.txt", std::ios_base::trunc);
// debug_text << "world coords:" << verify_tile.world_x()<< "," << verify_tile.world_y()<< "," << verify_tile.world_z() << std::endl;
// for(int i = 0; i < verify_tile.tile_layer_size(); i++) {
// debug_text << "layer: " << i << std::endl;
// for(int j = 0; j < 48; j++) {
// debug_text << " ";
// for(int k = 0; k < 48; k++) {
// debug_text << verify_tile.tile_layer(i).mat_type_table(j*48+k) << ",";
// }
// debug_text << " ";
// for(int k = 0; k < 48; k++) {
// debug_text << std::setw(3) << verify_tile.tile_layer(i).mat_subtype_table(j*48+k) << ",";
// }
// debug_text << std::endl;
// }
// debug_text << std::endl;
// }
// EmbarkTile verify_tile;
// verify_tile.ParseFromString(input_string);
// //write contents to text file.
// std::ofstream debug_text("tile.txt", std::ios_base::trunc);
// debug_text << "world coords:" << verify_tile.world_x()<< "," << verify_tile.world_y()<< "," << verify_tile.world_z() << std::endl;
// for(int i = 0; i < verify_tile.tile_layer_size(); i++) {
// debug_text << "layer: " << i << std::endl;
// for(int j = 0; j < 48; j++) {
// debug_text << " ";
// for(int k = 0; k < 48; k++) {
// debug_text << verify_tile.tile_layer(i).mat_type_table(j*48+k) << ",";
// }
// debug_text << " ";
// for(int k = 0; k < 48; k++) {
// debug_text << std::setw(3) << verify_tile.tile_layer(i).mat_subtype_table(j*48+k) << ",";
// }
// debug_text << std::endl;
// }
// debug_text << std::endl;
// }
// // Give control back to DF.
// return CR_OK;
//}
@ -197,12 +197,12 @@ static command_result GetEmbarkInfo(color_ostream &stream, const MapRequest *in,
out->set_available(false);
return CR_OK;
}
if (in->has_save_folder()) { //If no save folder is given, it means we don't care.
if (!(in->save_folder() == world->cur_savegame.save_dir || in->save_folder() == "ANY")) { //isoworld has a different map loaded, don't bother trying to load tiles for it, we don't have them.
out->set_available(false);
return CR_OK;
}
}
if (in->has_save_folder()) { //If no save folder is given, it means we don't care.
if (!(in->save_folder() == world->cur_savegame.save_dir || in->save_folder() == "ANY")) { //isoworld has a different map loaded, don't bother trying to load tiles for it, we don't have them.
out->set_available(false);
return CR_OK;
}
}
out->set_available(true);
out->set_current_year(*cur_year);
out->set_current_season(*cur_season);
@ -344,12 +344,12 @@ static command_result GetRawNames(color_ostream &stream, const MapRequest *in, R
out->set_available(false);
return CR_OK;
}
if (in->has_save_folder()) { //If no save folder is given, it means we don't care.
if (!(in->save_folder() == world->cur_savegame.save_dir || in->save_folder() == "ANY")) { //isoworld has a different map loaded, don't bother trying to load tiles for it, we don't have them.
out->set_available(false);
return CR_OK;
}
}
if (in->has_save_folder()) { //If no save folder is given, it means we don't care.
if (!(in->save_folder() == world->cur_savegame.save_dir || in->save_folder() == "ANY")) { //isoworld has a different map loaded, don't bother trying to load tiles for it, we don't have them.
out->set_available(false);
return CR_OK;
}
}
out->set_available(true);
for(int i = 0; i < world->raws.inorganics.size(); i++){
out->add_inorganic(world->raws.inorganics[i]->id);

@ -1,24 +1,24 @@
local _ENV = mkmodule('plugins.building-hacks')
--[[
from native:
addBuilding(custom type,impassible fix (bool), consumed power, produced power, list of connection points,
update skip(0/nil to disable),table of frames,frame to tick ratio (-1 for machine control))
from here:
registerBuilding{
name -- custom workshop id e.g. SOAPMAKER << required!
fix_impassible -- make impassible tiles impassible to liquids too
consume -- how much machine power is needed to work
produce -- how much machine power is produced
gears -- a table or {x=?,y=?} of connection points for machines
action -- a table of number (how much ticks to skip) and a function which gets called on shop update
animate -- a table of
frames -- a table of
tables of 4 numbers (tile,fore,back,bright) OR
empty table (tile not modified) OR
from native:
addBuilding(custom type,impassible fix (bool), consumed power, produced power, list of connection points,
update skip(0/nil to disable),table of frames,frame to tick ratio (-1 for machine control))
from here:
registerBuilding{
name -- custom workshop id e.g. SOAPMAKER << required!
fix_impassible -- make impassible tiles impassible to liquids too
consume -- how much machine power is needed to work
produce -- how much machine power is produced
gears -- a table or {x=?,y=?} of connection points for machines
action -- a table of number (how much ticks to skip) and a function which gets called on shop update
animate -- a table of
frames -- a table of
tables of 4 numbers (tile,fore,back,bright) OR
empty table (tile not modified) OR
{x=<number> y=<number> + 4 numbers like in first case} -- this generates full frame even, usefull for animations that change little (1-2 tiles)
frameLenght -- how many ticks does one frame take OR
isMechanical -- a bool that says to try to match to mechanical system (i.e. how gears are turning)
}
frameLenght -- how many ticks does one frame take OR
isMechanical -- a bool that says to try to match to mechanical system (i.e. how gears are turning)
}
]]
_registeredStuff={}
local function unregall(state)
@ -29,23 +29,23 @@ local function unregall(state)
end
end
local function onUpdateLocal(workshop)
local f=_registeredStuff[workshop:getCustomType()]
if f then
f(workshop)
end
local f=_registeredStuff[workshop:getCustomType()]
if f then
f(workshop)
end
end
local function findCustomWorkshop(name)
local raws=df.global.world.raws.buildings.all
for k,v in ipairs(raws) do
if v.code==name then
return v
end
end
local raws=df.global.world.raws.buildings.all
for k,v in ipairs(raws) do
if v.code==name then
return v
end
end
end
local function registerUpdateAction(shopId,callback)
_registeredStuff[shopId]=callback
onUpdateAction._library=onUpdateLocal
dfhack.onStateChange.building_hacks=unregall
_registeredStuff[shopId]=callback
onUpdateAction._library=onUpdateLocal
dfhack.onStateChange.building_hacks=unregall
end
local function generateFrame(tiles,w,h)
local mTiles={}
@ -66,7 +66,7 @@ local function generateFrame(tiles,w,h)
return ret
end
local function processFrames(shop_def,frames)
local w,h=shop_def.dim_x,shop_def.dim_y
local w,h=shop_def.dim_x,shop_def.dim_y
for frame_id,frame in ipairs(frames) do
if frame[1].x~=nil then
frames[frame_id]=generateFrame(frame,w,h)
@ -75,35 +75,35 @@ local function processFrames(shop_def,frames)
return frames
end
function registerBuilding(args)
local shop_def=findCustomWorkshop(args.name)
local shop_id=shop_def.id
local fix_impassible
if args.fix_impassible then
fix_impassible=1
else
fix_impassible=0
end
local consume=args.consume or 0
local produce=args.produce or 0
local gears=args.gears or {}
local action=args.action --could be nil
local updateSkip=0
if action~=nil then
updateSkip=action[1]
registerUpdateAction(shop_id,action[2])
end
local animate=args.animate
local frameLength=1
local frames
if animate~=nil then
frameLength=animate.frameLength
if animate.isMechanical then
frameLength=-1
end
frames=processFrames(shop_def,animate.frames)
end
local roomSubset=args.canBeRoomSubset or -1
addBuilding(shop_id,fix_impassible,consume,produce,gears,updateSkip,frames,frameLength,roomSubset)
local shop_def=findCustomWorkshop(args.name)
local shop_id=shop_def.id
local fix_impassible
if args.fix_impassible then
fix_impassible=1
else
fix_impassible=0
end
local consume=args.consume or 0
local produce=args.produce or 0
local gears=args.gears or {}
local action=args.action --could be nil
local updateSkip=0
if action~=nil then
updateSkip=action[1]
registerUpdateAction(shop_id,action[2])
end
local animate=args.animate
local frameLength=1
local frames
if animate~=nil then
frameLength=animate.frameLength
if animate.isMechanical then
frameLength=-1
end
frames=processFrames(shop_def,animate.frames)
end
local roomSubset=args.canBeRoomSubset or -1
addBuilding(shop_id,fix_impassible,consume,produce,gears,updateSkip,frames,frameLength,roomSubset)
end
return _ENV

@ -211,26 +211,26 @@ function SimpleMenu:init(args)
self.items={}
end
function SimpleMenu:add(name,entry,hints)
table.insert(self.items,{entry,name,hints})
table.insert(self.items,{entry,name,hints})
end
function SimpleMenu:display()
print("Select choice (q exits):")
for p,c in pairs(self.items) do
print(string.format("%3d).%s",p,c[2]))
end
local ans
repeat
local r
r=dfhack.lineedit()
if r==nil then return end
if r=='q' then return end
ans=tonumber(r)
print("Select choice (q exits):")
for p,c in pairs(self.items) do
print(string.format("%3d).%s",p,c[2]))
end
local ans
repeat
local r
r=dfhack.lineedit()
if r==nil then return end
if r=='q' then return end
ans=tonumber(r)
if ans==nil or not(ans<=#self.items and ans>0) then
print("Invalid choice.")
end
if ans==nil or not(ans<=#self.items and ans>0) then
print("Invalid choice.")
end
until ans~=nil and (ans<=#self.items and ans>0)
until ans~=nil and (ans<=#self.items and ans>0)
if type(self.items[ans][1])=="function" then
self.items[ans][1]()
else

@ -3,94 +3,94 @@ local dfu=require("plugins.dfusion")
local tools=require("plugins.dfusion.tools")
menu=dfu.SimpleMenu()
function Reincarnate(trg_unit,swap_soul) --only for adventurer i guess
if swap_soul==nil then
swap_soul=true
end
local adv=trg_unit or df.global.world.units.active[0]
if adv.flags1.dead==false then
qerror("You are not dead (yet)!")
end
local hist_fig=dfhack.units.getNemesis(adv).figure
if hist_fig==nil then
qerror("No historical figure for adventurer...")
end
local events=df.global.world.history.events
local trg_hist_fig
for i=#events-1,0,-1 do -- reverse search because almost always it will be last entry
if df.history_event_hist_figure_diedst:is_instance(events[i]) then
--print("is instance:"..i)
if events[i].victim_hf==hist_fig.id then
--print("Is same id:"..i)
trg_hist_fig=events[i].slayer_hf
if trg_hist_fig then
trg_hist_fig=df.historical_figure.find(trg_hist_fig)
end
break
end
end
end
if trg_hist_fig ==nil then
qerror("Slayer not found")
end
if swap_soul==nil then
swap_soul=true
end
local adv=trg_unit or df.global.world.units.active[0]
if adv.flags1.dead==false then
qerror("You are not dead (yet)!")
end
local hist_fig=dfhack.units.getNemesis(adv).figure
if hist_fig==nil then
qerror("No historical figure for adventurer...")
end
local events=df.global.world.history.events
local trg_hist_fig
for i=#events-1,0,-1 do -- reverse search because almost always it will be last entry
if df.history_event_hist_figure_diedst:is_instance(events[i]) then
--print("is instance:"..i)
if events[i].victim_hf==hist_fig.id then
--print("Is same id:"..i)
trg_hist_fig=events[i].slayer_hf
if trg_hist_fig then
trg_hist_fig=df.historical_figure.find(trg_hist_fig)
end
break
end
end
end
if trg_hist_fig ==nil then
qerror("Slayer not found")
end
local trg_unit=trg_hist_fig.unit_id
if trg_unit==nil then
qerror("Unit id not found!")
end
local trg_unit_final=df.unit.find(trg_unit)
local trg_unit=trg_hist_fig.unit_id
if trg_unit==nil then
qerror("Unit id not found!")
end
local trg_unit_final=df.unit.find(trg_unit)
change_adv(trg_unit_final)
if swap_soul then --actually add a soul...
t_soul=adv.status.current_soul
adv.status.current_soul=df.NULL
adv.status.souls:resize(0)
trg_unit_final.status.current_soul=t_soul
trg_unit_final.status.souls:insert(#trg_unit_final.status.souls,t_soul)
end
change_adv(trg_unit_final)
if swap_soul then --actually add a soul...
t_soul=adv.status.current_soul
adv.status.current_soul=df.NULL
adv.status.souls:resize(0)
trg_unit_final.status.current_soul=t_soul
trg_unit_final.status.souls:insert(#trg_unit_final.status.souls,t_soul)
end
end
menu:add("Reincarnate",Reincarnate,{{df.unit,"optional"}})-- bool, optional
function change_adv(unit,nemesis)
if nemesis==nil then
nemesis=true --default value is nemesis switch too.
end
if unit==nil then
unit=dfhack.gui.getSelectedUnit()--getCreatureAtPointer()
end
if unit==nil then
error("Invalid unit!")
end
local other=df.global.world.units.active
local unit_indx
for k,v in pairs(other) do
if v==unit then
unit_indx=k
break
end
end
if unit_indx==nil then
error("Unit not found in array?!") --should not happen
end
other[unit_indx]=other[0]
other[0]=unit
if nemesis then --basicly copied from advtools plugin...
local nem=dfhack.units.getNemesis(unit)
local other_nem=dfhack.units.getNemesis(other[unit_indx])
if other_nem then
other_nem.flags[0]=false
other_nem.flags[1]=true
end
if nem then
nem.flags[0]=true
nem.flags[2]=true
for k,v in pairs(df.global.world.nemesis.all) do
if v.id==nem.id then
df.global.ui_advmode.player_id=k
end
end
else
qerror("Current unit does not have nemesis record, further working not guaranteed")
end
end
if nemesis==nil then
nemesis=true --default value is nemesis switch too.
end
if unit==nil then
unit=dfhack.gui.getSelectedUnit()--getCreatureAtPointer()
end
if unit==nil then
error("Invalid unit!")
end
local other=df.global.world.units.active
local unit_indx
for k,v in pairs(other) do
if v==unit then
unit_indx=k
break
end
end
if unit_indx==nil then
error("Unit not found in array?!") --should not happen
end
other[unit_indx]=other[0]
other[0]=unit
if nemesis then --basicly copied from advtools plugin...
local nem=dfhack.units.getNemesis(unit)
local other_nem=dfhack.units.getNemesis(other[unit_indx])
if other_nem then
other_nem.flags[0]=false
other_nem.flags[1]=true
end
if nem then
nem.flags[0]=true
nem.flags[2]=true
for k,v in pairs(df.global.world.nemesis.all) do
if v.id==nem.id then
df.global.ui_advmode.player_id=k
end
end
else
qerror("Current unit does not have nemesis record, further working not guaranteed")
end
end
end
menu:add("Change adventurer",change_adv)
function log_pos()

@ -20,203 +20,203 @@ function build_race_names()
end
end
function setrace(name)
local RaceTable=build_race_names()
print("Your current race is:"..df.global.world.raws.creatures.all[df.global.ui.race_id].creature_id)
local id
if name == nil then
print("Type new race's token name in full caps (q to quit):")
repeat
local entry=dfhack.lineedit()
if entry=="q" then
return
end
id=RaceTable[entry]
until id~=nil
else
id=RaceTable[name]
if id==nil then
error("Name not found!")
end
end
df.global.ui.race_id=id
local RaceTable=build_race_names()
print("Your current race is:"..df.global.world.raws.creatures.all[df.global.ui.race_id].creature_id)
local id
if name == nil then
print("Type new race's token name in full caps (q to quit):")
repeat
local entry=dfhack.lineedit()
if entry=="q" then
return
end
id=RaceTable[entry]
until id~=nil
else
id=RaceTable[name]
if id==nil then
error("Name not found!")
end
end
df.global.ui.race_id=id
end
menu:add("Set current race",setrace)
function GiveSentience(names)
local RaceTable=build_race_names() --slow.If loaded don't load again
local RaceTable=build_race_names() --slow.If loaded don't load again
local id,ids
if names ==nil then
ids={}
print("Type race's token name in full caps to give sentience to:")
repeat
id=dfhack.lineedit()
id=RaceTable[entry]
if names ==nil then
ids={}
print("Type race's token name in full caps to give sentience to:")
repeat
id=dfhack.lineedit()
id=RaceTable[entry]
if id~=nil then
table.insert(ids,id)
end
until id==nil
until id==nil
else
ids={}
for _,name in pairs(names) do
id=RaceTable[name]
table.insert(ids,id)
end
end
for _,id in pairs(ids) do
local races=df.global.world.raws.creatures.all
else
ids={}
for _,name in pairs(names) do
id=RaceTable[name]
table.insert(ids,id)
end
end
for _,id in pairs(ids) do
local races=df.global.world.raws.creatures.all
local castes=races[id].caste
print(string.format("Caste count:%i",#castes))
for i =0,#castes-1 do
local castes=races[id].caste
print(string.format("Caste count:%i",#castes))
for i =0,#castes-1 do
print("Caste name:"..castes[i].caste_id.."...")
print("Caste name:"..castes[i].caste_id.."...")
local flags=castes[i].flags
--print(string.format("%x",flagoffset))
if flags.CAN_SPEAK then
print("\tis sentient.")
else
print("\tnon sentient. Allocating IQ...")
flags.CAN_SPEAK=true
end
end
end
local flags=castes[i].flags
--print(string.format("%x",flagoffset))
if flags.CAN_SPEAK then
print("\tis sentient.")
else
print("\tnon sentient. Allocating IQ...")
flags.CAN_SPEAK=true
end
end
end
end
menu:add("Give Sentience",GiveSentience)
function MakeFollow(unit,trgunit)
if unit == nil then
unit=dfhack.gui.getSelectedUnit()
end
if unit== nil then
error("Invalid creature")
end
if trgunit==nil then
trgunit=df.global.world.units.active[0]
end
unit.relations.group_leader_id=trgunit.id
local u_nem=dfhack.units.getNemesis(unit)
local t_nem=dfhack.units.getNemesis(trgunit)
if u_nem then
u_nem.group_leader_id=t_nem.id
end
if t_nem and u_nem then
t_nem.companions:insert(#t_nem.companions,u_nem.id)
end
if unit == nil then
unit=dfhack.gui.getSelectedUnit()
end
if unit== nil then
error("Invalid creature")
end
if trgunit==nil then
trgunit=df.global.world.units.active[0]
end
unit.relations.group_leader_id=trgunit.id
local u_nem=dfhack.units.getNemesis(unit)
local t_nem=dfhack.units.getNemesis(trgunit)
if u_nem then
u_nem.group_leader_id=t_nem.id
end
if t_nem and u_nem then
t_nem.companions:insert(#t_nem.companions,u_nem.id)
end
end
menu:add("Make creature follow",MakeFollow)
function project(unit,trg) --TODO add to menu?
if unit==nil then
unit=getCreatureAtPointer()
end
if unit==nil then
unit=getCreatureAtPointer()
end
if unit==nil then
error("Failed to project unit. Unit not selected/valid")
end
-- todo: add projectile to world, point to unit, add flag to unit, add gen-ref to projectile.
local p=df.proj_unitst:new()
local startpos={x=unit.pos.x,y=unit.pos.y,z=unit.pos.z}
p.origin_pos=startpos
p.target_pos=trg
p.cur_pos=startpos
p.prev_pos=startpos
p.unit=unit
--- wtf stuff
p.unk14=100
p.unk16=-1
p.unk23=-1
p.fall_delay=5
p.fall_counter=5
p.collided=true
-- end wtf
local citem=df.global.world.proj_list
local maxid=1
local newlink=df.proj_list_link:new()
newlink.item=p
while citem.item~= nil do
if citem.item.id>maxid then maxid=citem.item.id end
if citem.next ~= nil then
citem=citem.next
else
break
end
end
p.id=maxid+1
newlink.prev=citem
citem.next=newlink
local proj_ref=df.general_ref_projectile:new()
proj_ref.projectile_id=p.id
unit.general_refs:insert(#unit.general_refs,proj_ref)
unit.flags1.projectile=true
if unit==nil then
error("Failed to project unit. Unit not selected/valid")
end
-- todo: add projectile to world, point to unit, add flag to unit, add gen-ref to projectile.
local p=df.proj_unitst:new()
local startpos={x=unit.pos.x,y=unit.pos.y,z=unit.pos.z}
p.origin_pos=startpos
p.target_pos=trg
p.cur_pos=startpos
p.prev_pos=startpos
p.unit=unit
--- wtf stuff
p.unk14=100
p.unk16=-1
p.unk23=-1
p.fall_delay=5
p.fall_counter=5
p.collided=true
-- end wtf
local citem=df.global.world.proj_list
local maxid=1
local newlink=df.proj_list_link:new()
newlink.item=p
while citem.item~= nil do
if citem.item.id>maxid then maxid=citem.item.id end
if citem.next ~= nil then
citem=citem.next
else
break
end
end
p.id=maxid+1
newlink.prev=citem
citem.next=newlink
local proj_ref=df.general_ref_projectile:new()
proj_ref.projectile_id=p.id
unit.general_refs:insert(#unit.general_refs,proj_ref)
unit.flags1.projectile=true
end
function empregnate(unit)
if unit==nil then
unit=dfhack.gui.getSelectedUnit()
end
if unit==nil then
error("Failed to empregnate. Unit not selected/valid")
end
if unit.curse then
unit.curse.add_tags2.STERILE=false
end
local genes = unit.appearance.genes
if unit.relations.pregnancy_genes == nil then
print("creating preg ptr.")
if false then
print(string.format("%x %x",df.sizeof(unit.relations:_field("pregnancy_genes"))))
return
end
unit.relations.pregnancy_genes = { new = true, assign = genes }
end
local ngenes = unit.relations.pregnancy_genes
if #ngenes.appearance ~= #genes.appearance or #ngenes.colors ~= #genes.colors then
print("Array sizes incorrect, fixing.")
ngenes:assign(genes);
end
print("Setting preg timer.")
unit.relations.pregnancy_timer=10
unit.relations.pregnancy_caste=1
if unit==nil then
unit=dfhack.gui.getSelectedUnit()
end
if unit==nil then
error("Failed to empregnate. Unit not selected/valid")
end
if unit.curse then
unit.curse.add_tags2.STERILE=false
end
local genes = unit.appearance.genes
if unit.relations.pregnancy_genes == nil then
print("creating preg ptr.")
if false then
print(string.format("%x %x",df.sizeof(unit.relations:_field("pregnancy_genes"))))
return
end
unit.relations.pregnancy_genes = { new = true, assign = genes }
end
local ngenes = unit.relations.pregnancy_genes
if #ngenes.appearance ~= #genes.appearance or #ngenes.colors ~= #genes.colors then
print("Array sizes incorrect, fixing.")
ngenes:assign(genes);
end
print("Setting preg timer.")
unit.relations.pregnancy_timer=10
unit.relations.pregnancy_caste=1
end
menu:add("Empregnate",empregnate)
function healunit(unit)
if unit==nil then
unit=dfhack.gui.getSelectedUnit()
end
unit=dfhack.gui.getSelectedUnit()
end
if unit==nil then
error("Failed to Heal unit. Unit not selected/valid")
end
if unit==nil then
error("Failed to Heal unit. Unit not selected/valid")
end
unit.body.wounds:resize(0) -- memory leak here :/
unit.body.blood_count=unit.body.blood_max
--set flags for standing and grasping...
unit.status2.limbs_stand_max=4
unit.status2.limbs_stand_count=4
unit.status2.limbs_grasp_max=4
unit.status2.limbs_grasp_count=4
--should also set temperatures, and flags for breath etc...
unit.flags1.dead=false
unit.flags2.calculated_bodyparts=false
unit.flags2.calculated_nerves=false
unit.flags2.circulatory_spray=false
unit.flags2.vision_good=true
unit.flags2.vision_damaged=false
unit.flags2.vision_missing=false
unit.counters.winded=0
unit.counters.unconscious=0
for k,v in pairs(unit.body.components) do
for kk,vv in pairs(v) do
if k == 'body_part_status' then v[kk].whole = 0 else v[kk] = 0 end
end
end
unit.body.blood_count=unit.body.blood_max
--set flags for standing and grasping...
unit.status2.limbs_stand_max=4
unit.status2.limbs_stand_count=4
unit.status2.limbs_grasp_max=4
unit.status2.limbs_grasp_count=4
--should also set temperatures, and flags for breath etc...
unit.flags1.dead=false
unit.flags2.calculated_bodyparts=false
unit.flags2.calculated_nerves=false
unit.flags2.circulatory_spray=false
unit.flags2.vision_good=true
unit.flags2.vision_damaged=false
unit.flags2.vision_missing=false
unit.counters.winded=0
unit.counters.unconscious=0
for k,v in pairs(unit.body.components) do
for kk,vv in pairs(v) do
if k == 'body_part_status' then v[kk].whole = 0 else v[kk] = 0 end
end
end
end
menu:add("Heal unit",healunit)
function powerup(unit,labor_rating,military_rating,skills)
if unit==nil then
unit=dfhack.gui.getSelectedUnit()
end
if unit==nil then
error("Failed to power up unit. Unit not selected/valid")
end
unit=dfhack.gui.getSelectedUnit()
end
if unit==nil then
error("Failed to power up unit. Unit not selected/valid")
end
if unit.status.current_soul== nil then
error("Failed to power up unit. Unit has no soul")

@ -5,23 +5,23 @@ message Tile
{
enum TileType
{
EMPTY = 0;
FLOOR = 1;
BOULDER = 2;
PEBBLES = 3;
WALL = 4;
FORTIFICATION = 5;
STAIR_UP = 6;
STAIR_DOWN = 7;
STAIR_UPDOWN = 8;
RAMP = 9;
RAMP_TOP = 10;
BROOK_BED = 11;
BROOK_TOP = 12;
TREE = 13;
SAPLING = 14;
SHRUB = 15;
ENDLESS_PIT = 16;
EMPTY = 0;
FLOOR = 1;
BOULDER = 2;
PEBBLES = 3;
WALL = 4;
FORTIFICATION = 5;
STAIR_UP = 6;
STAIR_DOWN = 7;
STAIR_UPDOWN = 8;
RAMP = 9;
RAMP_TOP = 10;
BROOK_BED = 11;
BROOK_TOP = 12;
TREE = 13;
SAPLING = 14;
SHRUB = 15;
ENDLESS_PIT = 16;
}
enum LiquidType
{
@ -49,8 +49,8 @@ message Tile
MAGMA_TYPE = 16;
DRIFTWOOD = 17;
POOL = 18;
BROOK = 19;
RIVER = 20;
BROOK = 19;
RIVER = 20;
}
required uint32 x = 1;
required uint32 y = 2;

@ -6,203 +6,203 @@ option optimize_for = LITE_RUNTIME;
//We use shapes, etc, because the actual tiletypes may differ between DF versions.
enum TiletypeShape
{
NO_SHAPE = -1;
EMPTY = 0;
FLOOR = 1;
BOULDER = 2;
PEBBLES = 3;
WALL = 4;
FORTIFICATION = 5;
STAIR_UP = 6;
STAIR_DOWN = 7;
STAIR_UPDOWN = 8;
RAMP = 9;
RAMP_TOP = 10;
BROOK_BED = 11;
BROOK_TOP = 12;
TREE_SHAPE = 13;
SAPLING = 14;
SHRUB = 15;
ENDLESS_PIT = 16;
BRANCH = 17;
TRUNK_BRANCH = 18;
TWIG = 19;
NO_SHAPE = -1;
EMPTY = 0;
FLOOR = 1;
BOULDER = 2;
PEBBLES = 3;
WALL = 4;
FORTIFICATION = 5;
STAIR_UP = 6;
STAIR_DOWN = 7;
STAIR_UPDOWN = 8;
RAMP = 9;
RAMP_TOP = 10;
BROOK_BED = 11;
BROOK_TOP = 12;
TREE_SHAPE = 13;
SAPLING = 14;
SHRUB = 15;
ENDLESS_PIT = 16;
BRANCH = 17;
TRUNK_BRANCH = 18;
TWIG = 19;
}
enum TiletypeSpecial
{
NO_SPECIAL = -1;
NORMAL = 0;
RIVER_SOURCE = 1;
WATERFALL = 2;
SMOOTH = 3;
FURROWED = 4;
WET = 5;
DEAD = 6;
WORN_1 = 7;
WORN_2 = 8;
WORN_3 = 9;
TRACK = 10;
SMOOTH_DEAD = 11;
NO_SPECIAL = -1;
NORMAL = 0;
RIVER_SOURCE = 1;
WATERFALL = 2;
SMOOTH = 3;
FURROWED = 4;
WET = 5;
DEAD = 6;
WORN_1 = 7;
WORN_2 = 8;
WORN_3 = 9;
TRACK = 10;
SMOOTH_DEAD = 11;
};
enum TiletypeMaterial
{
NO_MATERIAL = -1;
AIR = 0;
SOIL = 1;
STONE = 2;
FEATURE = 3;
LAVA_STONE = 4;
MINERAL = 5;
FROZEN_LIQUID = 6;
CONSTRUCTION = 7;
GRASS_LIGHT = 8;
GRASS_DARK = 9;
GRASS_DRY = 10;
GRASS_DEAD = 11;
PLANT = 12;
HFS = 13;
CAMPFIRE = 14;
FIRE = 15;
ASHES = 16;
MAGMA = 17;
DRIFTWOOD = 18;
POOL = 19;
BROOK = 20;
RIVER = 21;
ROOT = 22;
TREE_MATERIAL = 23;
MUSHROOM = 24;
UNDERWORLD_GATE = 25;
NO_MATERIAL = -1;
AIR = 0;
SOIL = 1;
STONE = 2;
FEATURE = 3;
LAVA_STONE = 4;
MINERAL = 5;
FROZEN_LIQUID = 6;
CONSTRUCTION = 7;
GRASS_LIGHT = 8;
GRASS_DARK = 9;
GRASS_DRY = 10;
GRASS_DEAD = 11;
PLANT = 12;
HFS = 13;
CAMPFIRE = 14;
FIRE = 15;
ASHES = 16;
MAGMA = 17;
DRIFTWOOD = 18;
POOL = 19;
BROOK = 20;
RIVER = 21;
ROOT = 22;
TREE_MATERIAL = 23;
MUSHROOM = 24;
UNDERWORLD_GATE = 25;
}
enum TiletypeVariant
{
NO_VARIANT = -1;
VAR_1 = 0;
VAR_2 = 1;
VAR_3 = 2;
VAR_4 = 3;
NO_VARIANT = -1;
VAR_1 = 0;
VAR_2 = 1;
VAR_3 = 2;
VAR_4 = 3;
};
message Tiletype
{
required int32 id = 1;
optional string name = 2;
optional string caption = 3;
optional TiletypeShape shape = 4;
optional TiletypeSpecial special = 5;
optional TiletypeMaterial material = 6;
optional TiletypeVariant variant = 7;
optional string direction = 8;
required int32 id = 1;
optional string name = 2;
optional string caption = 3;
optional TiletypeShape shape = 4;
optional TiletypeSpecial special = 5;
optional TiletypeMaterial material = 6;
optional TiletypeVariant variant = 7;
optional string direction = 8;
};
message TiletypeList
{
repeated Tiletype tiletype_list = 1;
repeated Tiletype tiletype_list = 1;
}
message MapBlock
{
required int32 map_x = 1;
required int32 map_y = 2;
required int32 map_z = 3;
repeated int32 tiles = 4;
repeated MatPair materials = 5;
repeated MatPair layer_materials = 6;
repeated MatPair vein_materials = 7;
repeated MatPair base_materials = 8;
repeated int32 magma = 9;
repeated int32 water = 10;
required int32 map_x = 1;
required int32 map_y = 2;
required int32 map_z = 3;
repeated int32 tiles = 4;
repeated MatPair materials = 5;
repeated MatPair layer_materials = 6;
repeated MatPair vein_materials = 7;
repeated MatPair base_materials = 8;
repeated int32 magma = 9;
repeated int32 water = 10;
}
message MatPair {
required int32 mat_type = 1;
required int32 mat_index = 2;
required int32 mat_type = 1;
required int32 mat_index = 2;
}
message ColorDefinition {
required int32 red = 1;
required int32 green = 2;
required int32 blue = 3;
required int32 red = 1;
required int32 green = 2;
required int32 blue = 3;
}
message MaterialDefinition{
required MatPair mat_pair = 1;
optional string id = 2;
optional string name = 3;
optional ColorDefinition state_color = 4; //Simplifying colors to assume room temperature.
required MatPair mat_pair = 1;
optional string id = 2;
optional string name = 3;
optional ColorDefinition state_color = 4; //Simplifying colors to assume room temperature.
}
message MaterialList{
repeated MaterialDefinition material_list = 1;
repeated MaterialDefinition material_list = 1;
}
message UnitDefinition
{
required int32 id = 1;
optional bool isValid = 2;
optional int32 pos_x = 3;
optional int32 pos_y = 4;
optional int32 pos_z = 5;
required int32 id = 1;
optional bool isValid = 2;
optional int32 pos_x = 3;
optional int32 pos_y = 4;
optional int32 pos_z = 5;
}
message UnitList
{
repeated UnitDefinition creature_list = 1;
repeated UnitDefinition creature_list = 1;
}
message BlockRequest
{
optional int32 blocks_needed = 1;
optional int32 min_x = 2;
optional int32 max_x = 3;
optional int32 min_y = 4;
optional int32 max_y = 5;
optional int32 min_z = 6;
optional int32 max_z = 7;
optional int32 blocks_needed = 1;
optional int32 min_x = 2;
optional int32 max_x = 3;
optional int32 min_y = 4;
optional int32 max_y = 5;
optional int32 min_z = 6;
optional int32 max_z = 7;
}
message BlockList
{
repeated MapBlock map_blocks = 1;
optional int32 map_x = 2;
optional int32 map_y = 3;
repeated MapBlock map_blocks = 1;
optional int32 map_x = 2;
optional int32 map_y = 3;
}
message PlantDef
{
required int32 pos_x = 1;
required int32 pos_y = 2;
required int32 pos_z = 3;
required int32 index = 4;
required int32 pos_x = 1;
required int32 pos_y = 2;
required int32 pos_z = 3;
required int32 index = 4;
}
message PlantList
{
repeated PlantDef plant_list = 1;
repeated PlantDef plant_list = 1;
}
message ViewInfo
{
optional int32 view_pos_x = 1;
optional int32 view_pos_y = 2;
optional int32 view_pos_z = 3;
optional int32 view_size_x = 4;
optional int32 view_size_y = 5;
optional int32 cursor_pos_x = 6;
optional int32 cursor_pos_y = 7;
optional int32 cursor_pos_z = 8;
optional int32 view_pos_x = 1;
optional int32 view_pos_y = 2;
optional int32 view_pos_z = 3;
optional int32 view_size_x = 4;
optional int32 view_size_y = 5;
optional int32 cursor_pos_x = 6;
optional int32 cursor_pos_y = 7;
optional int32 cursor_pos_z = 8;
}
message MapInfo
{
optional int32 block_size_x = 1;
optional int32 block_size_y = 2;
optional int32 block_size_z = 3;
optional int32 block_pos_x = 4;
optional int32 block_pos_y = 5;
optional int32 block_pos_z = 6;
optional string world_name = 7;
optional string world_name_english = 8;
optional string save_name = 9;
optional int32 block_size_x = 1;
optional int32 block_size_y = 2;
optional int32 block_size_z = 3;
optional int32 block_pos_x = 4;
optional int32 block_pos_y = 5;
optional int32 block_pos_z = 6;
optional string world_name = 7;
optional string world_name_english = 8;
optional string save_name = 9;
}

@ -4,73 +4,73 @@ package isoworldremote;
option optimize_for = LITE_RUNTIME;
enum BasicMaterial {
AIR = 0;
OTHER = 1;
INORGANIC = 2;
LIQUID = 3;
PLANT = 4;
WOOD = 5;
AIR = 0;
OTHER = 1;
INORGANIC = 2;
LIQUID = 3;
PLANT = 4;
WOOD = 5;
};
enum LiquidType {
ICE = 0;
WATER = 1;
MAGMA = 2;
ICE = 0;
WATER = 1;
MAGMA = 2;
}
enum BasicShape {
NONE = 0;
OPEN = 1;
WALL = 3;
FLOOR = 4;
RAMP_UP = 5;
RAMP_DOWN = 6;
NONE = 0;
OPEN = 1;
WALL = 3;
FLOOR = 4;
RAMP_UP = 5;
RAMP_DOWN = 6;
}
message ColorDefinition {
required int32 red = 1;
required int32 green = 2;
required int32 blue = 3;
required int32 red = 1;
required int32 green = 2;
required int32 blue = 3;
}
message EmbarkTileLayer {
repeated BasicMaterial mat_type_table = 4 [packed=true];
repeated int32 mat_subtype_table = 5 [packed=true];
repeated BasicShape tile_shape_table = 6 [packed=true];
repeated ColorDefinition tile_color_table = 7;
repeated BasicMaterial mat_type_table = 4 [packed=true];
repeated int32 mat_subtype_table = 5 [packed=true];
repeated BasicShape tile_shape_table = 6 [packed=true];
repeated ColorDefinition tile_color_table = 7;
}
message EmbarkTile {
required int32 world_x = 1;
required int32 world_y = 2;
required sint32 world_z = 3;
repeated EmbarkTileLayer tile_layer = 4;
optional int32 current_year = 5;
optional int32 current_season = 6;
optional bool is_valid = 7;
required int32 world_x = 1;
required int32 world_y = 2;
required sint32 world_z = 3;
repeated EmbarkTileLayer tile_layer = 4;
optional int32 current_year = 5;
optional int32 current_season = 6;
optional bool is_valid = 7;
}
message TileRequest {
optional int32 want_x = 1;
optional int32 want_y = 2;
optional int32 want_x = 1;
optional int32 want_y = 2;
}
message MapRequest {
optional string save_folder = 1;
optional string save_folder = 1;
}
message MapReply {
required bool available = 1;
optional int32 region_x = 2;
optional int32 region_y = 3;
optional int32 region_size_x = 4;
optional int32 region_size_y = 5;
optional int32 current_year = 6;
optional int32 current_season = 7;
required bool available = 1;
optional int32 region_x = 2;
optional int32 region_y = 3;
optional int32 region_size_x = 4;
optional int32 region_size_y = 5;
optional int32 current_year = 6;
optional int32 current_season = 7;
}
message RawNames {
required bool available = 1;
repeated string inorganic = 2;
repeated string organic = 3;
required bool available = 1;
repeated string inorganic = 2;
repeated string organic = 3;
}

@ -276,7 +276,7 @@ class lightingEngineViewscreen:public lightingEngine
{
public:
lightingEngineViewscreen(renderer_light* target);
~lightingEngineViewscreen();
~lightingEngineViewscreen();
void reinit();
void calculate();
@ -296,7 +296,7 @@ private:
rgbf propogateSun(MapExtras::Block* b, int x,int y,const rgbf& in,bool lastLevel);
void doRay(std::vector<rgbf> & target, rgbf power,int cx,int cy,int tx,int ty);
void doFovs();
void doLight(std::vector<rgbf> & target, int index);
void doLight(std::vector<rgbf> & target, int index);
rgbf lightUpCell(std::vector<rgbf> & target, rgbf power,int dx,int dy,int tx,int ty);
bool addLight(int tileId,const lightSource& light);
void addOclusion(int tileId,const rgbf& c,float thickness);
@ -333,7 +333,7 @@ private:
int getW()const {return w;}
int getH()const {return h;}
public:
void lightWorkerThread(void * arg);
void lightWorkerThread(void * arg);
private:
rgbf getSkyColor(float v);
bool doDebug;

@ -11,164 +11,164 @@ for k,v in pairs(ret) do
end
-- add material by id (index,mat pair or token string or a type number), flags is a table of strings
-- supported flags (but not implemented):
-- flicker
-- flicker
function addMaterial(id,transparency,emitance,radius,flags)
local matinfo
if type(id)=="string" then
matinfo=dfhack.matinfo.find(id)
elseif type(id)=="table" then
matinfo=dfhack.matinfo.decode(id[1],id[2])
else
matinfo=dfhack.matinfo.decode(id,0)
end
if matinfo==nil then
error("Material not found")
end
materials[matinfo.type]=materials[matinfo.type] or {}
materials[matinfo.type][matinfo.index]=makeMaterialDef(transparency,emitance,radius,flags)
local matinfo
if type(id)=="string" then
matinfo=dfhack.matinfo.find(id)
elseif type(id)=="table" then
matinfo=dfhack.matinfo.decode(id[1],id[2])
else
matinfo=dfhack.matinfo.decode(id,0)
end
if matinfo==nil then
error("Material not found")
end
materials[matinfo.type]=materials[matinfo.type] or {}
materials[matinfo.type][matinfo.index]=makeMaterialDef(transparency,emitance,radius,flags)
end
function buildingLookUp(id)
local tokens={}
local lookup={ Workshop=df.workshop_type,Furnace=df.furnace_type,Trap=df.trap_type,
SiegeEngine=df.siegeengine_type}
for i in string.gmatch(id, "[^:]+") do
table.insert(tokens,i)
end
local ret={}
ret.type=df.building_type[tokens[1]]
if tokens[2] then
local type_array=lookup[tokens[1]]
if type_array then
ret.subtype=type_array[tokens[2]]
end
if tokens[2]=="Custom" and tokens[3] then --TODO cache for faster lookup
if ret.type==df.building_type.Workshop then
for k,v in pairs(df.global.world.raws.buildings.workshops) do
if v.code==tokens[3] then
ret.custom=v.id
return ret
end
end
elseif ret.type==df.building_type.Furnace then
for k,v in pairs(df.global.world.raws.buildings.furnaces) do
if v.code==tokens[3] then
ret.custom=v.id
return ret
end
end
end
end
qerror("Invalid custom building:"..tokens[3])
end
return ret
local tokens={}
local lookup={ Workshop=df.workshop_type,Furnace=df.furnace_type,Trap=df.trap_type,
SiegeEngine=df.siegeengine_type}
for i in string.gmatch(id, "[^:]+") do
table.insert(tokens,i)
end
local ret={}
ret.type=df.building_type[tokens[1]]
if tokens[2] then
local type_array=lookup[tokens[1]]
if type_array then
ret.subtype=type_array[tokens[2]]
end
if tokens[2]=="Custom" and tokens[3] then --TODO cache for faster lookup
if ret.type==df.building_type.Workshop then
for k,v in pairs(df.global.world.raws.buildings.workshops) do
if v.code==tokens[3] then
ret.custom=v.id
return ret
end
end
elseif ret.type==df.building_type.Furnace then
for k,v in pairs(df.global.world.raws.buildings.furnaces) do
if v.code==tokens[3] then
ret.custom=v.id
return ret
end
end
end
end
qerror("Invalid custom building:"..tokens[3])
end
return ret
end
function itemLookup(id)
local ret={}
local tokens={}
for i in string.gmatch(id, "[^:]+") do
table.insert(tokens,i)
end
ret.type=df.item_type[tokens[1]]
ret.subtype=-1
if tokens[2] then
for k,v in ipairs(df.global.world.raws.itemdefs.all) do --todo lookup correct itemdef
if v.id==tokens[2] then
ret.subtype=v.subtype
return ret
end
end
qerror("Failed item subtype lookup:"..tokens[2])
end
return ret
local ret={}
local tokens={}
for i in string.gmatch(id, "[^:]+") do
table.insert(tokens,i)
end
ret.type=df.item_type[tokens[1]]
ret.subtype=-1
if tokens[2] then
for k,v in ipairs(df.global.world.raws.itemdefs.all) do --todo lookup correct itemdef
if v.id==tokens[2] then
ret.subtype=v.subtype
return ret
end
end
qerror("Failed item subtype lookup:"..tokens[2])
end
return ret
end
function creatureLookup(id)
local ret={}
local tokens={}
for i in string.gmatch(id, "[^:]+") do
table.insert(tokens,i)
end
for k,v in ipairs(df.global.world.raws.creatures.all) do
if v.creature_id==tokens[1] then
ret.type=k
if tokens[2] then
for k,v in ipairs(v.caste) do
if v.caste_id==tokens[2] then
ret.subtype=k
break
end
end
if ret.subtype==nil then
qerror("caste "..tokens[2].." for "..tokens[1].." not found")
end
end
return ret
end
end
qerror("Failed to find race:"..tokens[1])
local ret={}
local tokens={}
for i in string.gmatch(id, "[^:]+") do
table.insert(tokens,i)
end
for k,v in ipairs(df.global.world.raws.creatures.all) do
if v.creature_id==tokens[1] then
ret.type=k
if tokens[2] then
for k,v in ipairs(v.caste) do
if v.caste_id==tokens[2] then
ret.subtype=k
break
end
end
if ret.subtype==nil then
qerror("caste "..tokens[2].." for "..tokens[1].." not found")
end
end
return ret
end
end
qerror("Failed to find race:"..tokens[1])
end
-- add creature by id ("DWARF" or "DWARF:MALE")
-- supported flags:
function addCreature(id,transparency,emitance,radius,flags)
local crId=creatureLookup(id)
local mat=makeMaterialDef(transparency,emitance,radius,flags)
table.insert(creatures,{race=crId.type,caste=crId.subtype or -1, light=mat})
local crId=creatureLookup(id)
local mat=makeMaterialDef(transparency,emitance,radius,flags)
table.insert(creatures,{race=crId.type,caste=crId.subtype or -1, light=mat})
end
-- add item by id ( "TOTEM" or "WEAPON:PICK" or "WEAPON" for all the weapon types)
-- supported flags:
-- hauling --active when hauled TODO::currently all mean same thing...
-- equiped --active while equiped TODO::currently all mean same thing...
-- inBuilding --active in building TODO::currently all mean same thing...
-- contained --active in container TODO::currently all mean same thing...
-- onGround --active on ground
-- useMaterial --uses material, but the defined things overwrite
-- hauling --active when hauled TODO::currently all mean same thing...
-- equiped --active while equiped TODO::currently all mean same thing...
-- inBuilding --active in building TODO::currently all mean same thing...
-- contained --active in container TODO::currently all mean same thing...
-- onGround --active on ground
-- useMaterial --uses material, but the defined things overwrite
function addItem(id,transparency,emitance,radius,flags)
local itemId=itemLookup(id)
local mat=makeMaterialDef(transparency,emitance,radius,flags)
table.insert(items,{["type"]=itemId.type,subtype=itemId.subtype,light=mat})
local itemId=itemLookup(id)
local mat=makeMaterialDef(transparency,emitance,radius,flags)
table.insert(items,{["type"]=itemId.type,subtype=itemId.subtype,light=mat})
end
-- add building by id (string e.g. "Statue" or "Workshop:Masons", flags is a table of strings
-- supported flags:
-- useMaterial --uses material, but the defined things overwrite
-- poweredOnly --glow only when powered
-- useMaterial --uses material, but the defined things overwrite
-- poweredOnly --glow only when powered
function addBuilding(id,transparency,emitance,radius,flags,size,thickness)
size=size or 1
thickness=thickness or 1
local bld=buildingLookUp(id)
local mat=makeMaterialDef(transparency,emitance,radius,flags)
mat.size=size
mat.thickness=thickness
buildings[bld.type]=buildings[bld.type] or {}
if bld.subtype then
if bld.custom then
buildings[bld.type][bld.subtype]=buildings[bld.type][bld.subtype] or {}
buildings[bld.type][bld.subtype][bld.custom]=mat
else
buildings[bld.type][bld.subtype]={[-1]=mat}
end
else
buildings[bld.type][-1]={[-1]=mat}
end
size=size or 1
thickness=thickness or 1
local bld=buildingLookUp(id)
local mat=makeMaterialDef(transparency,emitance,radius,flags)
mat.size=size
mat.thickness=thickness
buildings[bld.type]=buildings[bld.type] or {}
if bld.subtype then
if bld.custom then
buildings[bld.type][bld.subtype]=buildings[bld.type][bld.subtype] or {}
buildings[bld.type][bld.subtype][bld.custom]=mat
else
buildings[bld.type][bld.subtype]={[-1]=mat}
end
else
buildings[bld.type][-1]={[-1]=mat}
end
end
function makeMaterialDef(transparency,emitance,radius,flags)
local flg
if flags then
flg={}
for k,v in ipairs(flags) do
flg[v]=true
end
end
return {tr=transparency,em=emitance,rad=radius,flags=flg}
local flg
if flags then
flg={}
for k,v in ipairs(flags) do
flg[v]=true
end
end
return {tr=transparency,em=emitance,rad=radius,flags=flg}
end
function colorFrom16(col16)
local col=df.global.enabler.ccolor[col16]
return {col[0],col[1],col[2]}
local col=df.global.enabler.ccolor[col16]
return {col[0],col[1],col[2]}
end
function addGems()
for k,v in pairs(df.global.world.raws.inorganics) do
if v.material.flags.IS_GEM then
addMaterial("INORGANIC:"..v.id,colorFrom16(v.material.tile_color[0]+v.material.tile_color[2]*8))
end
end
for k,v in pairs(df.global.world.raws.inorganics) do
if v.material.flags.IS_GEM then
addMaterial("INORGANIC:"..v.id,colorFrom16(v.material.tile_color[0]+v.material.tile_color[2]*8))
end
end
end
------------------------------------------------------------------------
---------------- Configuration Starts Here -------------------------
@ -184,30 +184,30 @@ special.CITIZEN=makeMaterialDef(nil,{0.80,0.80,0.90},6)
special.LevelDim=0.2 -- darkness. Do not set to 0
special.dayHour=-1 -- <0 cycle, else hour of the day
special.dayColors={ {0,0,0}, --dark at 0 hours
{0.6,0.5,0.5}, --reddish twilight
{1,1,1}, --fullbright at 12 hours
{0.5,0.5,0.5},
{0,0,0}} --dark at 24 hours
{0.6,0.5,0.5}, --reddish twilight
{1,1,1}, --fullbright at 12 hours
{0.5,0.5,0.5},
{0,0,0}} --dark at 24 hours
special.daySpeed=1 -- 1->1200 cur_year_ticks per day. 2->600 ticks
special.diffusionCount=1 -- split beam max 1 times to mimic diffuse lights
special.advMode=0 -- 1 or 0 different modes for adv mode. 0-> use df vision system,
-- 1(does not work)->everything visible, let rendermax light do the work
-- 1(does not work)->everything visible, let rendermax light do the work
--TODO dragonfire
--materials
-- glasses
-- glasses
addMaterial("GLASS_GREEN",{0.1,0.9,0.5})
addMaterial("GLASS_CLEAR",{0.5,0.95,0.9})
addMaterial("GLASS_CRYSTAL",{0.75,0.95,0.95})
-- Plants
-- Plants
addMaterial("PLANT:TOWER_CAP",nil,{0.65,0.65,0.65},6)
addMaterial("PLANT:MUSHROOM_CUP_DIMPLE",nil,{0.03,0.03,0.5},3)
addMaterial("PLANT:CAVE MOSS",nil,{0.1,0.1,0.4},2)
addMaterial("PLANT:MUSHROOM_HELMET_PLUMP",nil,{0.2,0.1,0.6},2)
-- inorganics
-- inorganics
addMaterial("INORGANIC:ADAMANTINE",{0.1,0.3,0.3},{0.1,0.3,0.3},4)
-- creature stuff
-- creature stuff
addMaterial("CREATURE:DRAGON:BLOOD",nil,{0.6,0.1,0.1},4)
addGems()
--buildings

@ -1 +1 @@
Subproject commit 8270ef2892b640a2e5753844a5e917ba96523fbb
Subproject commit a8c5bd263306050ac1dc21140ce52719b0dd598b

@ -1,136 +1,136 @@
class AutoFarm
def initialize
@thresholds = Hash.new(50)
@lastcounts = Hash.new(0)
end
def setthreshold(id, v)
list = df.world.raws.plants.all.find_all { |plt| plt.flags[:SEED] }.map { |plt| plt.id }
if tok = df.match_rawname(id, list)
@thresholds[tok] = v.to_i
else
puts "No plant with id #{id}, try one of " +
list.map { |w| w =~ /[^\w]/ ? w.inspect : w }.sort.join(' ')
end
end
def setdefault(v)
@thresholds.default = v.to_i
end
def is_plantable(plant)
has_seed = plant.flags[:SEED]
season = df.cur_season
harvest = df.cur_season_tick + plant.growdur * 10
will_finish = harvest < 10080
can_plant = has_seed && plant.flags[season]
can_plant = can_plant && (will_finish || plant.flags[(season+1)%4])
can_plant
end
def find_plantable_plants
plantable = {}
counts = Hash.new(0)
df.world.items.other[:SEEDS].each { |i|
if (!i.flags.dump && !i.flags.forbid && !i.flags.garbage_collect &&
!i.flags.hostile && !i.flags.on_fire && !i.flags.rotten &&
!i.flags.trader && !i.flags.in_building && !i.flags.construction &&
!i.flags.artifact)
counts[i.mat_index] += i.stack_size
end
}
counts.keys.each { |i|
if df.ui.tasks.discovered_plants[i]
plant = df.world.raws.plants.all[i]
if is_plantable(plant)
plantable[i] = :Surface if (plant.underground_depth_min == 0 || plant.underground_depth_max == 0)
plantable[i] = :Underground if (plant.underground_depth_min > 0 || plant.underground_depth_max > 0)
end
end
}
return plantable
end
def set_farms(plants, farms)
return if farms.length == 0
if plants.length == 0
plants = [-1]
end
season = df.cur_season
farms.each_with_index { |f, idx|
f.plant_id[season] = plants[idx % plants.length]
}
end
def process
plantable = find_plantable_plants
@lastcounts = Hash.new(0)
df.world.items.other[:PLANT].each { |i|
if (!i.flags.dump && !i.flags.forbid && !i.flags.garbage_collect &&
!i.flags.hostile && !i.flags.on_fire && !i.flags.rotten &&
!i.flags.trader && !i.flags.in_building && !i.flags.construction &&
!i.flags.artifact && plantable.has_key?(i.mat_index))
id = df.world.raws.plants.all[i.mat_index].id
@lastcounts[id] += i.stack_size
end
}
return unless @running
plants_s = []
plants_u = []
plantable.each_key { |k|
plant = df.world.raws.plants.all[k]
if (@lastcounts[plant.id] < @thresholds[plant.id])
plants_s.push(k) if plantable[k] == :Surface
plants_u.push(k) if plantable[k] == :Underground
end
}
farms_s = []
farms_u = []
df.world.buildings.other[:FARM_PLOT].each { |f|
if (f.flags.exists)
underground = df.map_designation_at(f.centerx,f.centery,f.z).subterranean
farms_s.push(f) unless underground
farms_u.push(f) if underground
end
}
set_farms(plants_s, farms_s)
set_farms(plants_u, farms_u)
end
def start
return if @running
@onupdate = df.onupdate_register('autofarm', 1200) { process }
@running = true
end
def stop
df.onupdate_unregister(@onupdate)
@running = false
end
def status
stat = @running ? "Running." : "Stopped."
@lastcounts.each { |k,v|
stat << "\n#{k} limit #{@thresholds.fetch(k, 'default')} current #{v}"
}
@thresholds.each { |k,v|
stat << "\n#{k} limit #{v} current 0" unless @lastcounts.has_key?(k)
}
stat << "\nDefault: #{@thresholds.default}"
stat
end
def initialize
@thresholds = Hash.new(50)
@lastcounts = Hash.new(0)
end
def setthreshold(id, v)
list = df.world.raws.plants.all.find_all { |plt| plt.flags[:SEED] }.map { |plt| plt.id }
if tok = df.match_rawname(id, list)
@thresholds[tok] = v.to_i
else
puts "No plant with id #{id}, try one of " +
list.map { |w| w =~ /[^\w]/ ? w.inspect : w }.sort.join(' ')
end
end
def setdefault(v)
@thresholds.default = v.to_i
end
def is_plantable(plant)
has_seed = plant.flags[:SEED]
season = df.cur_season
harvest = df.cur_season_tick + plant.growdur * 10
will_finish = harvest < 10080
can_plant = has_seed && plant.flags[season]
can_plant = can_plant && (will_finish || plant.flags[(season+1)%4])
can_plant
end
def find_plantable_plants
plantable = {}
counts = Hash.new(0)
df.world.items.other[:SEEDS].each { |i|
if (!i.flags.dump && !i.flags.forbid && !i.flags.garbage_collect &&
!i.flags.hostile && !i.flags.on_fire && !i.flags.rotten &&
!i.flags.trader && !i.flags.in_building && !i.flags.construction &&
!i.flags.artifact)
counts[i.mat_index] += i.stack_size
end
}
counts.keys.each { |i|
if df.ui.tasks.discovered_plants[i]
plant = df.world.raws.plants.all[i]
if is_plantable(plant)
plantable[i] = :Surface if (plant.underground_depth_min == 0 || plant.underground_depth_max == 0)
plantable[i] = :Underground if (plant.underground_depth_min > 0 || plant.underground_depth_max > 0)
end
end
}
return plantable
end
def set_farms(plants, farms)
return if farms.length == 0
if plants.length == 0
plants = [-1]
end
season = df.cur_season
farms.each_with_index { |f, idx|
f.plant_id[season] = plants[idx % plants.length]
}
end
def process
plantable = find_plantable_plants
@lastcounts = Hash.new(0)
df.world.items.other[:PLANT].each { |i|
if (!i.flags.dump && !i.flags.forbid && !i.flags.garbage_collect &&
!i.flags.hostile && !i.flags.on_fire && !i.flags.rotten &&
!i.flags.trader && !i.flags.in_building && !i.flags.construction &&
!i.flags.artifact && plantable.has_key?(i.mat_index))
id = df.world.raws.plants.all[i.mat_index].id
@lastcounts[id] += i.stack_size
end
}
return unless @running
plants_s = []
plants_u = []
plantable.each_key { |k|
plant = df.world.raws.plants.all[k]
if (@lastcounts[plant.id] < @thresholds[plant.id])
plants_s.push(k) if plantable[k] == :Surface
plants_u.push(k) if plantable[k] == :Underground
end
}
farms_s = []
farms_u = []
df.world.buildings.other[:FARM_PLOT].each { |f|
if (f.flags.exists)
underground = df.map_designation_at(f.centerx,f.centery,f.z).subterranean
farms_s.push(f) unless underground
farms_u.push(f) if underground
end
}
set_farms(plants_s, farms_s)
set_farms(plants_u, farms_u)
end
def start
return if @running
@onupdate = df.onupdate_register('autofarm', 1200) { process }
@running = true
end
def stop
df.onupdate_unregister(@onupdate)
@running = false
end
def status
stat = @running ? "Running." : "Stopped."
@lastcounts.each { |k,v|
stat << "\n#{k} limit #{@thresholds.fetch(k, 'default')} current #{v}"
}
@thresholds.each { |k,v|
stat << "\n#{k} limit #{v} current 0" unless @lastcounts.has_key?(k)
}
stat << "\nDefault: #{@thresholds.default}"
stat
end
end
@ -138,28 +138,28 @@ $AutoFarm ||= AutoFarm.new
case $script_args[0]
when 'start', 'enable'
$AutoFarm.start
puts $AutoFarm.status
$AutoFarm.start
puts $AutoFarm.status
when 'end', 'stop', 'disable'
$AutoFarm.stop
puts 'Stopped.'
$AutoFarm.stop
puts 'Stopped.'
when 'default'
$AutoFarm.setdefault($script_args[1])
$AutoFarm.setdefault($script_args[1])
when 'threshold'
t = $script_args[1]
$script_args[2..-1].each {|i|
$AutoFarm.setthreshold(i, t)
}
t = $script_args[1]
$script_args[2..-1].each {|i|
$AutoFarm.setthreshold(i, t)
}
when 'delete'
$AutoFarm.stop
$AutoFarm = nil
$AutoFarm.stop
$AutoFarm = nil
when 'help', '?'
puts <<EOS
puts <<EOS
Automatically handle crop selection in farm plots based on current plant stocks.
Selects a crop for planting if current stock is below a threshold.
Selected crops are dispatched on all farmplots.
@ -171,6 +171,6 @@ Usage:
EOS
else
$AutoFarm.process
puts $AutoFarm.status
$AutoFarm.process
puts $AutoFarm.status
end

@ -8,7 +8,7 @@ count = $script_args[2]
category = df.match_rawname(category, ['help', 'bars', 'boulders', 'plants', 'logs', 'webs', 'anvils']) || 'help'
if category == 'help'
puts <<EOS
puts <<EOS
Create first necessity items under the cursor.
Usage:
create-items [category] [raws token] [number]
@ -28,118 +28,118 @@ Exemples:
create-items plants list
EOS
throw :script_finished
throw :script_finished
elsif mat_raw == 'list'
# allowed with no cursor
# allowed with no cursor
elsif df.cursor.x == -30000
puts "Please place the game cursor somewhere"
throw :script_finished
puts "Please place the game cursor somewhere"
throw :script_finished
elsif !(maptile = df.map_tile_at(df.cursor))
puts "Error: unallocated map block !"
throw :script_finished
puts "Error: unallocated map block !"
throw :script_finished
elsif !maptile.shape_passablehigh
puts "Error: impassible tile !"
throw :script_finished
puts "Error: impassible tile !"
throw :script_finished
end
def match_list(tok, list)
if tok != 'list'
tok = df.match_rawname(tok, list)
if not tok
puts "Invalid raws token, use one in:"
tok = 'list'
end
end
if tok == 'list'
puts list.map { |w| w =~ /[^\w]/ ? w.inspect : w }.join(' ')
throw :script_finished
end
tok
if tok != 'list'
tok = df.match_rawname(tok, list)
if not tok
puts "Invalid raws token, use one in:"
tok = 'list'
end
end
if tok == 'list'
puts list.map { |w| w =~ /[^\w]/ ? w.inspect : w }.join(' ')
throw :script_finished
end
tok
end
case category
when 'bars'
# create metal bar, eg createbar INORGANIC:IRON
cls = DFHack::ItemBarst
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
list = df.world.raws.inorganics.find_all { |ino|
ino.material.flags[:IS_METAL]
}.map { |ino| ino.id }
mat_raw = match_list(mat_raw, list)
mat_raw = "INORGANIC:#{mat_raw}"
puts mat_raw
end
customize = lambda { |item|
item.dimension = 150
item.subtype = -1
}
# create metal bar, eg createbar INORGANIC:IRON
cls = DFHack::ItemBarst
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
list = df.world.raws.inorganics.find_all { |ino|
ino.material.flags[:IS_METAL]
}.map { |ino| ino.id }
mat_raw = match_list(mat_raw, list)
mat_raw = "INORGANIC:#{mat_raw}"
puts mat_raw
end
customize = lambda { |item|
item.dimension = 150
item.subtype = -1
}
when 'boulders'
cls = DFHack::ItemBoulderst
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
list = df.world.raws.inorganics.find_all { |ino|
ino.material.flags[:IS_STONE]
}.map { |ino| ino.id }
mat_raw = match_list(mat_raw, list)
mat_raw = "INORGANIC:#{mat_raw}"
puts mat_raw
end
cls = DFHack::ItemBoulderst
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
list = df.world.raws.inorganics.find_all { |ino|
ino.material.flags[:IS_STONE]
}.map { |ino| ino.id }
mat_raw = match_list(mat_raw, list)
mat_raw = "INORGANIC:#{mat_raw}"
puts mat_raw
end
when 'plants'
cls = DFHack::ItemPlantst
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
list = df.world.raws.plants.all.find_all { |plt|
plt.material.find { |mat| mat.id == 'STRUCTURAL' }
}.map { |plt| plt.id }
mat_raw = match_list(mat_raw, list)
mat_raw = "PLANT_MAT:#{mat_raw}:STRUCTURAL"
puts mat_raw
end
cls = DFHack::ItemPlantst
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
list = df.world.raws.plants.all.find_all { |plt|
plt.material.find { |mat| mat.id == 'STRUCTURAL' }
}.map { |plt| plt.id }
mat_raw = match_list(mat_raw, list)
mat_raw = "PLANT_MAT:#{mat_raw}:STRUCTURAL"
puts mat_raw
end
when 'logs'
cls = DFHack::ItemWoodst
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
list = df.world.raws.plants.all.find_all { |plt|
plt.material.find { |mat| mat.id == 'WOOD' }
}.map { |plt| plt.id }
mat_raw = match_list(mat_raw, list)
mat_raw = "PLANT_MAT:#{mat_raw}:WOOD"
puts mat_raw
end
cls = DFHack::ItemWoodst
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
list = df.world.raws.plants.all.find_all { |plt|
plt.material.find { |mat| mat.id == 'WOOD' }
}.map { |plt| plt.id }
mat_raw = match_list(mat_raw, list)
mat_raw = "PLANT_MAT:#{mat_raw}:WOOD"
puts mat_raw
end
when 'webs'
cls = DFHack::ItemThreadst
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
list = df.world.raws.creatures.all.find_all { |cre|
cre.material.find { |mat| mat.id == 'SILK' }
}.map { |cre| cre.creature_id }
mat_raw = match_list(mat_raw, list)
mat_raw = "CREATURE_MAT:#{mat_raw}:SILK"
puts mat_raw
end
count ||= 1
customize = lambda { |item|
item.flags.spider_web = true
item.dimension = 15000 # XXX may depend on creature (this is for GCS)
}
cls = DFHack::ItemThreadst
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
list = df.world.raws.creatures.all.find_all { |cre|
cre.material.find { |mat| mat.id == 'SILK' }
}.map { |cre| cre.creature_id }
mat_raw = match_list(mat_raw, list)
mat_raw = "CREATURE_MAT:#{mat_raw}:SILK"
puts mat_raw
end
count ||= 1
customize = lambda { |item|
item.flags.spider_web = true
item.dimension = 15000 # XXX may depend on creature (this is for GCS)
}
when 'anvils'
cls = DFHack::ItemAnvilst
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
list = df.world.raws.inorganics.find_all { |ino|
ino.material.flags[:IS_METAL]
}.map { |ino| ino.id }
mat_raw = match_list(mat_raw, list)
mat_raw = "INORGANIC:#{mat_raw}"
puts mat_raw
end
count ||= 1
cls = DFHack::ItemAnvilst
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
list = df.world.raws.inorganics.find_all { |ino|
ino.material.flags[:IS_METAL]
}.map { |ino| ino.id }
mat_raw = match_list(mat_raw, list)
mat_raw = "INORGANIC:#{mat_raw}"
puts mat_raw
end
count ||= 1
end
@ -148,30 +148,30 @@ mat = df.decode_mat mat_raw
count ||= 20
count.to_i.times {
item = cls.cpp_new
item.id = df.item_next_id
item.stack_size = 1
item.mat_type = mat.mat_type
item.mat_index = mat.mat_index
customize[item] if customize
df.item_next_id += 1
item.categorize(true)
df.world.items.all << item
item.pos = df.cursor
item.flags.on_ground = true
df.map_tile_at.mapblock.items << item.id
df.map_tile_at.occupancy.item = true
item = cls.cpp_new
item.id = df.item_next_id
item.stack_size = 1
item.mat_type = mat.mat_type
item.mat_index = mat.mat_index
customize[item] if customize
df.item_next_id += 1
item.categorize(true)
df.world.items.all << item
item.pos = df.cursor
item.flags.on_ground = true
df.map_tile_at.mapblock.items << item.id
df.map_tile_at.occupancy.item = true
}
# move game view, so that the ui menu updates
if df.cursor.z > 5
df.curview.feed_keys(:CURSOR_DOWN_Z)
df.curview.feed_keys(:CURSOR_UP_Z)
df.curview.feed_keys(:CURSOR_DOWN_Z)
df.curview.feed_keys(:CURSOR_UP_Z)
else
df.curview.feed_keys(:CURSOR_UP_Z)
df.curview.feed_keys(:CURSOR_DOWN_Z)
df.curview.feed_keys(:CURSOR_UP_Z)
df.curview.feed_keys(:CURSOR_DOWN_Z)
end

@ -1,67 +1,67 @@
# show death cause of a creature
def display_death_event(e)
str = "The #{e.victim_hf_tg.race_tg.name[0]} #{e.victim_hf_tg.name} died in year #{e.year}"
str << " (cause: #{e.death_cause.to_s.downcase}),"
str << " killed by the #{e.slayer_race_tg.name[0]} #{e.slayer_hf_tg.name}" if e.slayer_hf != -1
str << " using a #{df.world.raws.itemdefs.weapons[e.weapon.item_subtype].name}" if e.weapon.item_type == :WEAPON
str << ", shot by a #{df.world.raws.itemdefs.weapons[e.weapon.shooter_item_subtype].name}" if e.weapon.shooter_item_type == :WEAPON
str = "The #{e.victim_hf_tg.race_tg.name[0]} #{e.victim_hf_tg.name} died in year #{e.year}"
str << " (cause: #{e.death_cause.to_s.downcase}),"
str << " killed by the #{e.slayer_race_tg.name[0]} #{e.slayer_hf_tg.name}" if e.slayer_hf != -1
str << " using a #{df.world.raws.itemdefs.weapons[e.weapon.item_subtype].name}" if e.weapon.item_type == :WEAPON
str << ", shot by a #{df.world.raws.itemdefs.weapons[e.weapon.shooter_item_subtype].name}" if e.weapon.shooter_item_type == :WEAPON
puts str.chomp(',') + '.'
puts str.chomp(',') + '.'
end
def display_death_unit(u)
death_info = u.counters.death_tg
killer = death_info.killer_tg if death_info
death_info = u.counters.death_tg
killer = death_info.killer_tg if death_info
str = "The #{u.race_tg.name[0]}"
str << " #{u.name}" if u.name.has_name
str << " died"
str << " in year #{death_info.event_year}" if death_info
str << " (cause: #{u.counters.death_cause.to_s.downcase})," if u.counters.death_cause != -1
str << " killed by the #{killer.race_tg.name[0]} #{killer.name}" if killer
str = "The #{u.race_tg.name[0]}"
str << " #{u.name}" if u.name.has_name
str << " died"
str << " in year #{death_info.event_year}" if death_info
str << " (cause: #{u.counters.death_cause.to_s.downcase})," if u.counters.death_cause != -1
str << " killed by the #{killer.race_tg.name[0]} #{killer.name}" if killer
puts str.chomp(',') + '.'
puts str.chomp(',') + '.'
end
item = df.item_find(:selected)
unit = df.unit_find(:selected)
if !item or !item.kind_of?(DFHack::ItemBodyComponent)
item = df.world.items.other[:ANY_CORPSE].find { |i| df.at_cursor?(i) }
item = df.world.items.other[:ANY_CORPSE].find { |i| df.at_cursor?(i) }
end
if item and item.kind_of?(DFHack::ItemBodyComponent)
hf = item.hist_figure_id
hf = item.hist_figure_id
elsif unit
hf = unit.hist_figure_id
hf = unit.hist_figure_id
end
if not hf
puts "Please select a corpse in the loo'k' menu, or an unit in the 'u'nitlist screen"
puts "Please select a corpse in the loo'k' menu, or an unit in the 'u'nitlist screen"
elsif hf == -1
if unit ||= item.unit_tg
display_death_unit(unit)
else
puts "Not a historical figure, cannot death find info"
end
if unit ||= item.unit_tg
display_death_unit(unit)
else
puts "Not a historical figure, cannot death find info"
end
else
histfig = df.world.history.figures.binsearch(hf)
unit = histfig ? df.unit_find(histfig.unit_id) : nil
if unit and not unit.flags1.dead and not unit.flags3.ghostly
puts "#{unit.name} is not dead yet !"
histfig = df.world.history.figures.binsearch(hf)
unit = histfig ? df.unit_find(histfig.unit_id) : nil
if unit and not unit.flags1.dead and not unit.flags3.ghostly
puts "#{unit.name} is not dead yet !"
else
events = df.world.history.events
(0...events.length).reverse_each { |i|
e = events[i]
if e.kind_of?(DFHack::HistoryEventHistFigureDiedst) and e.victim_hf == hf
display_death_event(e)
break
end
}
end
else
events = df.world.history.events
(0...events.length).reverse_each { |i|
e = events[i]
if e.kind_of?(DFHack::HistoryEventHistFigureDiedst) and e.victim_hf == hf
display_death_event(e)
break
end
}
end
end

@ -9,49 +9,49 @@ local tile_attrs = df.tiletype.attrs
local args={...}
function setCell(x,y,cell)
cell=cell or {}
cell.fm=cell.fm or {r=1,g=1,b=1}
cell.bm=cell.bm or {r=1,g=1,b=1}
cell.fo=cell.fo or {r=0,g=0,b=0}
cell.bo=cell.bo or {r=0,g=0,b=0}
render.setCell(x,y,cell)
cell=cell or {}
cell.fm=cell.fm or {r=1,g=1,b=1}
cell.bm=cell.bm or {r=1,g=1,b=1}
cell.fo=cell.fo or {r=0,g=0,b=0}
cell.bo=cell.bo or {r=0,g=0,b=0}
render.setCell(x,y,cell)
end
function getCursorPos()
local g_cursor=df.global.cursor
local g_cursor=df.global.cursor
if g_cursor.x ~= -30000 then
return copyall(g_cursor)
end
end
function falloff(color,sqDist,maxdist)
local v1=1/(sqDist/maxdist+1)
local v2=v1-1/(1+maxdist*maxdist)
local v=v2/(1-1/(1+maxdist*maxdist))
return {r=v*color.r,g=v*color.g,b=v*color.b}
local v1=1/(sqDist/maxdist+1)
local v2=v1-1/(1+maxdist*maxdist)
local v=v2/(1-1/(1+maxdist*maxdist))
return {r=v*color.r,g=v*color.g,b=v*color.b}
end
function blend(c1,c2)
return {r=math.max(c1.r,c2.r),
g=math.max(c1.g,c2.g),
b=math.max(c1.b,c2.b)}
g=math.max(c1.g,c2.g),
b=math.max(c1.b,c2.b)}
end
LightOverlay=defclass(LightOverlay,guidm.DwarfOverlay)
LightOverlay.ATTRS {
lightMap={},
dynamic=true,
dirty=false,
dynamic=true,
dirty=false,
}
function LightOverlay:init(args)
self.tick=df.global.cur_year_tick_advmode
self.tick=df.global.cur_year_tick_advmode
end
function lightPassable(shape)
if shape==df.tiletype_shape.WALL or
shape==df.tiletype_shape.BROOK_BED or
shape==df.tiletype_shape.TREE then
return false
else
return true
end
if shape==df.tiletype_shape.WALL or
shape==df.tiletype_shape.BROOK_BED or
shape==df.tiletype_shape.TREE then
return false
else
return true
end
end
function circle(xm, ym,r,plot)
local x = -r
@ -64,312 +64,312 @@ function circle(xm, ym,r,plot)
plot(xm+y, ym+x);--/* IV. Quadrant */
r = err;
if (r <= y) then
y=y+1
err =err+y*2+1; --/* e_xy+e_y < 0 */
end
y=y+1
err =err+y*2+1; --/* e_xy+e_y < 0 */
end
if (r > x or err > y) then
x=x+1
err =err+x*2+1; --/* e_xy+e_x > 0 or no 2nd y-step */
end
x=x+1
err =err+x*2+1; --/* e_xy+e_x > 0 or no 2nd y-step */
end
until (x >= 0);
end
function line(x0, y0, x1, y1,plot)
local dx = math.abs(x1-x0)
local dy = math.abs(y1-y0)
local sx,sy
if x0 < x1 then sx = 1 else sx = -1 end
if y0 < y1 then sy = 1 else sy = -1 end
local err = dx-dy
local dx = math.abs(x1-x0)
local dy = math.abs(y1-y0)
local sx,sy
if x0 < x1 then sx = 1 else sx = -1 end
if y0 < y1 then sy = 1 else sy = -1 end
local err = dx-dy
while true do
if not plot(x0,y0) then
return
end
if x0 == x1 and y0 == y1 then
break
end
local e2 = 2*err
if e2 > -dy then
err = err - dy
x0 = x0 + sx
end
if x0 == x1 and y0 == y1 then
if not plot(x0,y0) then
return
end
break
end
if e2 < dx then
err = err + dx
y0 = y0 + sy
end
end
while true do
if not plot(x0,y0) then
return
end
if x0 == x1 and y0 == y1 then
break
end
local e2 = 2*err
if e2 > -dy then
err = err - dy
x0 = x0 + sx
end
if x0 == x1 and y0 == y1 then
if not plot(x0,y0) then
return
end
break
end
if e2 < dx then
err = err + dx
y0 = y0 + sy
end
end
end
function LightOverlay:calculateFovs()
self.fovs=self.fovs or {}
self.precalc=self.precalc or {}
for k,v in ipairs(self.fovs) do
self:calculateFov(v.pos,v.radius,v.color)
end
self.fovs=self.fovs or {}
self.precalc=self.precalc or {}
for k,v in ipairs(self.fovs) do
self:calculateFov(v.pos,v.radius,v.color)
end
end
function LightOverlay:calculateFov(pos,radius,color)
local vp=self:getViewport()
local map = self.df_layout.map
local ray=function(tx,ty)
local power=copyall(color)
local lx=pos.x
local ly=pos.y
local setTile=function(x,y)
if x>0 and y>0 and x<=map.width and y<=map.height then
local dtsq=(lx-x)*(lx-x)+(ly-y)*(ly-y)
local dt=math.sqrt(dtsq)
local tile=x+y*map.width
if self.precalc[tile] then
local tcol=blend(self.precalc[tile],power)
if tcol.r==self.precalc[tile].r and tcol.g==self.precalc[tile].g and self.precalc[tile].b==self.precalc[tile].b
and dtsq>0 then
return false
end
end
local ocol=self.lightMap[tile] or {r=0,g=0,b=0}
local ncol=blend(power,ocol)
local vp=self:getViewport()
local map = self.df_layout.map
local ray=function(tx,ty)
local power=copyall(color)
local lx=pos.x
local ly=pos.y
local setTile=function(x,y)
if x>0 and y>0 and x<=map.width and y<=map.height then
local dtsq=(lx-x)*(lx-x)+(ly-y)*(ly-y)
local dt=math.sqrt(dtsq)
local tile=x+y*map.width
if self.precalc[tile] then
local tcol=blend(self.precalc[tile],power)
if tcol.r==self.precalc[tile].r and tcol.g==self.precalc[tile].g and self.precalc[tile].b==self.precalc[tile].b
and dtsq>0 then
return false
end
end
local ocol=self.lightMap[tile] or {r=0,g=0,b=0}
local ncol=blend(power,ocol)
self.lightMap[tile]=ncol
local v=self.ocupancy[tile]
if dtsq>0 then
power.r=power.r*(v.r^dt)
power.g=power.g*(v.g^dt)
power.b=power.b*(v.b^dt)
end
lx=x
ly=y
local pwsq=power.r*power.r+power.g*power.g+power.b*power.b
return pwsq>levelDim*levelDim
end
return false
end
line(pos.x,pos.y,tx,ty,setTile)
end
circle(pos.x,pos.y,radius,ray)
self.lightMap[tile]=ncol
local v=self.ocupancy[tile]
if dtsq>0 then
power.r=power.r*(v.r^dt)
power.g=power.g*(v.g^dt)
power.b=power.b*(v.b^dt)
end
lx=x
ly=y
local pwsq=power.r*power.r+power.g*power.g+power.b*power.b
return pwsq>levelDim*levelDim
end
return false
end
line(pos.x,pos.y,tx,ty,setTile)
end
circle(pos.x,pos.y,radius,ray)
end
function LightOverlay:placeLightFov(pos,radius,color)
local map = self.df_layout.map
local tile=pos.x+pos.y*map.width
local ocol=self.precalc[tile] or {r=0,g=0,b=0}
local ncol=blend(color,ocol)
self.precalc[tile]=ncol
local ocol=self.lightMap[tile] or {r=0,g=0,b=0}
local ncol=blend(color,ocol)
self.lightMap[tile]=ncol
table.insert(self.fovs,{pos=pos,radius=radius,color=color})
local map = self.df_layout.map
local tile=pos.x+pos.y*map.width
local ocol=self.precalc[tile] or {r=0,g=0,b=0}
local ncol=blend(color,ocol)
self.precalc[tile]=ncol
local ocol=self.lightMap[tile] or {r=0,g=0,b=0}
local ncol=blend(color,ocol)
self.lightMap[tile]=ncol
table.insert(self.fovs,{pos=pos,radius=radius,color=color})
end
function LightOverlay:placeLightFov2(pos,radius,color,f,rays)
f=f or falloff
local raycount=rays or 25
local vp=self:getViewport()
local map = self.df_layout.map
local off=math.random(0,math.pi)
local done={}
for d=0,math.pi*2,math.pi*2/raycount do
local dx,dy
dx=math.cos(d+off)
dy=math.sin(d+off)
local cx=0
local cy=0
f=f or falloff
local raycount=rays or 25
local vp=self:getViewport()
local map = self.df_layout.map
local off=math.random(0,math.pi)
local done={}
for d=0,math.pi*2,math.pi*2/raycount do
local dx,dy
dx=math.cos(d+off)
dy=math.sin(d+off)
local cx=0
local cy=0
for dt=0,radius,0.01 do
if math.abs(math.floor(dt*dx)-cx)>0 or math.abs(math.floor(dt*dy)-cy)> 0then
local x=cx+pos.x
local y=cy+pos.y
for dt=0,radius,0.01 do
if math.abs(math.floor(dt*dx)-cx)>0 or math.abs(math.floor(dt*dy)-cy)> 0then
local x=cx+pos.x
local y=cy+pos.y
if x>0 and y>0 and x<=map.width and y<=map.height and not done[tile] then
local tile=x+y*map.width
done[tile]=true
local ncol=f(color,dt*dt,radius)
local ocol=self.lightMap[tile] or {r=0,g=0,b=0}
ncol=blend(ncol,ocol)
self.lightMap[tile]=ncol
if x>0 and y>0 and x<=map.width and y<=map.height and not done[tile] then
local tile=x+y*map.width
done[tile]=true
local ncol=f(color,dt*dt,radius)
local ocol=self.lightMap[tile] or {r=0,g=0,b=0}
ncol=blend(ncol,ocol)
self.lightMap[tile]=ncol
if --(ncol.r==ocol.r and ncol.g==ocol.g and ncol.b==ocol.b) or
not self.ocupancy[tile] then
break
end
end
cx=math.floor(dt*dx)
cy=math.floor(dt*dy)
end
end
end
if --(ncol.r==ocol.r and ncol.g==ocol.g and ncol.b==ocol.b) or
not self.ocupancy[tile] then
break
end
end
cx=math.floor(dt*dx)
cy=math.floor(dt*dy)
end
end
end
end
function LightOverlay:placeLight(pos,radius,color,f)
f=f or falloff
local vp=self:getViewport()
local map = self.df_layout.map
f=f or falloff
local vp=self:getViewport()
local map = self.df_layout.map
for i=-radius,radius do
for j=-radius,radius do
local x=pos.x+i+1
local y=pos.y+j+1
if x>0 and y>0 and x<=map.width and y<=map.height then
local tile=x+y*map.width
local ncol=f(color,(i*i+j*j),radius)
local ocol=self.lightMap[tile] or {r=0,g=0,b=0}
self.lightMap[tile]=blend(ncol,ocol)
end
end
end
for i=-radius,radius do
for j=-radius,radius do
local x=pos.x+i+1
local y=pos.y+j+1
if x>0 and y>0 and x<=map.width and y<=map.height then
local tile=x+y*map.width
local ncol=f(color,(i*i+j*j),radius)
local ocol=self.lightMap[tile] or {r=0,g=0,b=0}
self.lightMap[tile]=blend(ncol,ocol)
end
end
end
end
function LightOverlay:calculateLightLava()
local vp=self:getViewport()
local map = self.df_layout.map
for i=map.x1,map.x2 do
for j=map.y1,map.y2 do
local pos={x=i+vp.x1-1,y=j+vp.y1-1,z=vp.z}
local pos2={x=i+vp.x1-1,y=j+vp.y1-1,z=vp.z-1}
local t1=dfhack.maps.getTileFlags(pos)
local tt=dfhack.maps.getTileType(pos)
if tt then
local shape=tile_attrs[tt].shape
local t2=dfhack.maps.getTileFlags(pos2)
if (t1 and t1.liquid_type and t1.flow_size>0) or
(shape==df.tiletype_shape.EMPTY and t2 and t2.liquid_type and t2.flow_size>0) then
--self:placeLight({x=i,y=j},5,{r=0.8,g=0.2,b=0.2})
self:placeLightFov({x=i,y=j},5,{r=0.8,g=0.2,b=0.2},nil)
end
end
end
end
local vp=self:getViewport()
local map = self.df_layout.map
for i=map.x1,map.x2 do
for j=map.y1,map.y2 do
local pos={x=i+vp.x1-1,y=j+vp.y1-1,z=vp.z}
local pos2={x=i+vp.x1-1,y=j+vp.y1-1,z=vp.z-1}
local t1=dfhack.maps.getTileFlags(pos)
local tt=dfhack.maps.getTileType(pos)
if tt then
local shape=tile_attrs[tt].shape
local t2=dfhack.maps.getTileFlags(pos2)
if (t1 and t1.liquid_type and t1.flow_size>0) or
(shape==df.tiletype_shape.EMPTY and t2 and t2.liquid_type and t2.flow_size>0) then
--self:placeLight({x=i,y=j},5,{r=0.8,g=0.2,b=0.2})
self:placeLightFov({x=i,y=j},5,{r=0.8,g=0.2,b=0.2},nil)
end
end
end
end
end
function LightOverlay:calculateLightSun()
local vp=self:getViewport()
local map = self.df_layout.map
for i=map.x1,map.x2+1 do
for j=map.y1,map.y2+1 do
local pos={x=i+vp.x1-1,y=j+vp.y1-1,z=vp.z}
local vp=self:getViewport()
local map = self.df_layout.map
for i=map.x1,map.x2+1 do
for j=map.y1,map.y2+1 do
local pos={x=i+vp.x1-1,y=j+vp.y1-1,z=vp.z}
local t1=dfhack.maps.getTileFlags(pos)
local t1=dfhack.maps.getTileFlags(pos)
if (t1 and t1.outside ) then
if (t1 and t1.outside ) then
self:placeLightFov({x=i,y=j},15,{r=1,g=1,b=1},nil)
end
end
end
self:placeLightFov({x=i,y=j},15,{r=1,g=1,b=1},nil)
end
end
end
end
function LightOverlay:calculateLightCursor()
local c=getCursorPos()
local c=getCursorPos()
if c then
if c then
local vp=self:getViewport()
local pos=vp:tileToScreen(c)
--self:placeLight(pos,11,{r=0.96,g=0.84,b=0.03})
self:placeLightFov({x=pos.x+1,y=pos.y+1},11,{r=0.96,g=0.84,b=0.03})
local vp=self:getViewport()
local pos=vp:tileToScreen(c)
--self:placeLight(pos,11,{r=0.96,g=0.84,b=0.03})
self:placeLightFov({x=pos.x+1,y=pos.y+1},11,{r=0.96,g=0.84,b=0.03})
end
end
end
function LightOverlay:buildOcupancy()
self.ocupancy={}
local vp=self:getViewport()
local map = self.df_layout.map
for i=map.x1,map.x2+1 do
for j=map.y1,map.y2+1 do
local pos={x=i+vp.x1-1,y=j+vp.y1-1,z=vp.z}
local tile=i+j*map.width
local tt=dfhack.maps.getTileType(pos)
local t1=dfhack.maps.getTileFlags(pos)
if tt then
local shape=tile_attrs[tt].shape
if not lightPassable(shape) then
self.ocupancy[tile]={r=0,g=0,b=0}
else
if t1 and not t1.liquid_type and t1.flow_size>2 then
self.ocupancy[tile]={r=0.5,g=0.5,b=0.7}
else
self.ocupancy[tile]={r=0.8,g=0.8,b=0.8}
end
end
end
end
end
self.ocupancy={}
local vp=self:getViewport()
local map = self.df_layout.map
for i=map.x1,map.x2+1 do
for j=map.y1,map.y2+1 do
local pos={x=i+vp.x1-1,y=j+vp.y1-1,z=vp.z}
local tile=i+j*map.width
local tt=dfhack.maps.getTileType(pos)
local t1=dfhack.maps.getTileFlags(pos)
if tt then
local shape=tile_attrs[tt].shape
if not lightPassable(shape) then
self.ocupancy[tile]={r=0,g=0,b=0}
else
if t1 and not t1.liquid_type and t1.flow_size>2 then
self.ocupancy[tile]={r=0.5,g=0.5,b=0.7}
else
self.ocupancy[tile]={r=0.8,g=0.8,b=0.8}
end
end
end
end
end
end
function LightOverlay:changed()
if self.dirty or self.tick~=df.global.cur_year_tick_advmode then
self.dirty=false
self.tick=df.global.cur_year_tick_advmode
return true
end
return false
if self.dirty or self.tick~=df.global.cur_year_tick_advmode then
self.dirty=false
self.tick=df.global.cur_year_tick_advmode
return true
end
return false
end
function LightOverlay:makeLightMap()
if not self:changed() then
return
end
self.fovs={}
self.precalc={}
self.lightMap={}
if not self:changed() then
return
end
self.fovs={}
self.precalc={}
self.lightMap={}
self:buildOcupancy()
self:calculateLightCursor()
self:calculateLightLava()
self:calculateLightSun()
self:buildOcupancy()
self:calculateLightCursor()
self:calculateLightLava()
self:calculateLightSun()
self:calculateFovs()
self:calculateFovs()
end
function LightOverlay:onIdle()
self._native.parent:logic()
self._native.parent:logic()
end
function LightOverlay:render(dc)
if self.dynamic then
self:makeLightMap()
end
self:renderParent()
local vp=self:getViewport()
local map = self.df_layout.map
if self.dynamic then
self:makeLightMap()
end
self:renderParent()
local vp=self:getViewport()
local map = self.df_layout.map
self.lightMap=self.lightMap or {}
render.lockGrids()
render.invalidate({x=map.x1,y=map.y1,w=map.width,h=map.height})
render.resetGrids()
for i=map.x1,map.x2 do
for j=map.y1,map.y2 do
local v=self.lightMap[i+j*map.width]
if v then
setCell(i,j,{fm=v,bm=v})
else
local dimRgb={r=levelDim,g=levelDim,b=levelDim}
setCell(i,j,{fm=dimRgb,bm=dimRgb})
end
end
end
render.unlockGrids()
self.lightMap=self.lightMap or {}
render.lockGrids()
render.invalidate({x=map.x1,y=map.y1,w=map.width,h=map.height})
render.resetGrids()
for i=map.x1,map.x2 do
for j=map.y1,map.y2 do
local v=self.lightMap[i+j*map.width]
if v then
setCell(i,j,{fm=v,bm=v})
else
local dimRgb={r=levelDim,g=levelDim,b=levelDim}
setCell(i,j,{fm=dimRgb,bm=dimRgb})
end
end
end
render.unlockGrids()
end
function LightOverlay:onDismiss()
render.lockGrids()
render.resetGrids()
render.invalidate()
render.unlockGrids()
render.lockGrids()
render.resetGrids()
render.invalidate()
render.unlockGrids()
end
function LightOverlay:onInput(keys)
if keys.STRING_A096 then
self:dismiss()
else
self:sendInputToParent(keys)
if keys.STRING_A096 then
self:dismiss()
else
self:sendInputToParent(keys)
if keys.CHANGETAB then
self:updateLayout()
end
if keys.STRING_A126 and not self.dynamic then
self:makeLightMap()
end
self.dirty=true
end
if keys.CHANGETAB then
self:updateLayout()
end
if keys.STRING_A126 and not self.dynamic then
self:makeLightMap()
end
self.dirty=true
end
end
if not render.isEnabled() then
qerror("Lua rendermode not enabled!")
qerror("Lua rendermode not enabled!")
end
local dyn=true
if #args>0 and args[1]=="static" then dyn=false end

@ -6,5 +6,5 @@ raise 'select an item' if not tg
o = df.world.items.other
# discard ANY/BAD
o._indexenum::ENUM.sort.transpose[1][1..-2].each { |k|
puts k if o[k].find { |i| i == tg }
puts k if o[k].find { |i| i == tg }
}

@ -4,10 +4,10 @@ df.world.arena_spawn.race.clear
df.world.arena_spawn.caste.clear
df.world.raws.creatures.all.length.times { |r_idx|
df.world.raws.creatures.all[r_idx].caste.length.times { |c_idx|
df.world.arena_spawn.race << r_idx
df.world.arena_spawn.caste << c_idx
}
df.world.raws.creatures.all[r_idx].caste.length.times { |c_idx|
df.world.arena_spawn.race << r_idx
df.world.arena_spawn.caste << c_idx
}
}
df.world.arena_spawn.creature_cnt[df.world.arena_spawn.race.length-1] = 0

@ -10,69 +10,69 @@ kill_by = $script_args[1]
case kill_by
when 'magma'
slain = 'burning'
slain = 'burning'
when 'slaughter', 'butcher'
slain = 'marked for butcher'
slain = 'marked for butcher'
when nil
slain = 'slain'
slain = 'slain'
else
race = 'help'
race = 'help'
end
checkunit = lambda { |u|
(u.body.blood_count != 0 or u.body.blood_max == 0) and
not u.flags1.dead and
not u.flags1.caged and not u.flags1.chained and
#not u.flags1.hidden_in_ambush and
not df.map_designation_at(u).hidden
(u.body.blood_count != 0 or u.body.blood_max == 0) and
not u.flags1.dead and
not u.flags1.caged and not u.flags1.chained and
#not u.flags1.hidden_in_ambush and
not df.map_designation_at(u).hidden
}
slayit = lambda { |u|
case kill_by
when 'magma'
# it's getting hot around here
# !!WARNING!! do not call on a magma-safe creature
ouh = df.onupdate_register("exterminate ensure #{u.id}", 1) {
if u.flags1.dead
df.onupdate_unregister(ouh)
else
x, y, z = u.pos.x, u.pos.y, u.pos.z
z += 1 while tile = df.map_tile_at(x, y, z+1) and
tile.shape_passableflow and tile.shape_passablelow
df.map_tile_at(x, y, z).spawn_magma(7)
end
}
when 'butcher', 'slaughter'
# mark for slaughter at butcher's shop
u.flags2.slaughter = true
else
# just make them drop dead
u.body.blood_count = 0
# some races dont mind having no blood, ensure they are still taken care of.
u.animal.vanish_countdown = 2
end
case kill_by
when 'magma'
# it's getting hot around here
# !!WARNING!! do not call on a magma-safe creature
ouh = df.onupdate_register("exterminate ensure #{u.id}", 1) {
if u.flags1.dead
df.onupdate_unregister(ouh)
else
x, y, z = u.pos.x, u.pos.y, u.pos.z
z += 1 while tile = df.map_tile_at(x, y, z+1) and
tile.shape_passableflow and tile.shape_passablelow
df.map_tile_at(x, y, z).spawn_magma(7)
end
}
when 'butcher', 'slaughter'
# mark for slaughter at butcher's shop
u.flags2.slaughter = true
else
# just make them drop dead
u.body.blood_count = 0
# some races dont mind having no blood, ensure they are still taken care of.
u.animal.vanish_countdown = 2
end
}
all_races = Hash.new(0)
df.world.units.active.map { |u|
if checkunit[u]
if (u.enemy.undead or
(u.curse.add_tags1.OPPOSED_TO_LIFE and not
u.curse.rem_tags1.OPPOSED_TO_LIFE))
all_races['Undead'] += 1
else
all_races[u.race_tg.creature_id] += 1
end
end
if checkunit[u]
if (u.enemy.undead or
(u.curse.add_tags1.OPPOSED_TO_LIFE and not
u.curse.rem_tags1.OPPOSED_TO_LIFE))
all_races['Undead'] += 1
else
all_races[u.race_tg.creature_id] += 1
end
end
}
case race
when nil
all_races.sort_by { |race, cnt| [cnt, race] }.each{ |race, cnt| puts " #{race} #{cnt}" }
all_races.sort_by { |race, cnt| [cnt, race] }.each{ |race, cnt| puts " #{race} #{cnt}" }
when 'help', '?'
puts <<EOS
puts <<EOS
Kills all creatures of a given race.
With no argument, lists possible targets with their head count.
With the special argument 'him' or 'her', kill only the currently selected creature.
@ -91,61 +91,61 @@ Ex: exterminate gob
EOS
when 'him', 'her', 'it', 'that'
if him = df.unit_find
case him.race_tg.caste[him.caste].gender
when 0; puts 'its a she !' if race != 'her'
when 1; puts 'its a he !' if race != 'him'
else; puts 'its an it !' if race != 'it' and race != 'that'
end
slayit[him]
else
puts "Select a target ingame"
end
if him = df.unit_find
case him.race_tg.caste[him.caste].gender
when 0; puts 'its a she !' if race != 'her'
when 1; puts 'its a he !' if race != 'him'
else; puts 'its an it !' if race != 'it' and race != 'that'
end
slayit[him]
else
puts "Select a target ingame"
end
when /^undead/i
count = 0
df.world.units.active.each { |u|
if (u.enemy.undead or
(u.curse.add_tags1.OPPOSED_TO_LIFE and not
u.curse.rem_tags1.OPPOSED_TO_LIFE)) and
checkunit[u]
slayit[u]
count += 1
end
}
puts "#{slain} #{count} undeads"
count = 0
df.world.units.active.each { |u|
if (u.enemy.undead or
(u.curse.add_tags1.OPPOSED_TO_LIFE and not
u.curse.rem_tags1.OPPOSED_TO_LIFE)) and
checkunit[u]
slayit[u]
count += 1
end
}
puts "#{slain} #{count} undeads"
else
if race.index(':')
race, caste = race.split(':')
end
raw_race = df.match_rawname(race, all_races.keys)
if not raw_race
puts "Invalid race, use one of #{all_races.keys.sort.join(' ')}"
throw :script_finished
end
race_nr = df.world.raws.creatures.all.index { |cr| cr.creature_id == raw_race }
if caste
all_castes = df.world.raws.creatures.all[race_nr].caste.map { |c| c.caste_id }
raw_caste = df.match_rawname(caste, all_castes)
if not raw_caste
puts "Invalid caste, use one of #{all_castes.sort.join(' ')}"
throw :script_finished
end
caste_nr = all_castes.index(raw_caste)
end
count = 0
df.world.units.active.each { |u|
if u.race == race_nr and checkunit[u]
next if caste_nr and u.caste != caste_nr
slayit[u]
count += 1
end
}
puts "#{slain} #{count} #{raw_caste} #{raw_race}"
if race.index(':')
race, caste = race.split(':')
end
raw_race = df.match_rawname(race, all_races.keys)
if not raw_race
puts "Invalid race, use one of #{all_races.keys.sort.join(' ')}"
throw :script_finished
end
race_nr = df.world.raws.creatures.all.index { |cr| cr.creature_id == raw_race }
if caste
all_castes = df.world.raws.creatures.all[race_nr].caste.map { |c| c.caste_id }
raw_caste = df.match_rawname(caste, all_castes)
if not raw_caste
puts "Invalid caste, use one of #{all_castes.sort.join(' ')}"
throw :script_finished
end
caste_nr = all_castes.index(raw_caste)
end
count = 0
df.world.units.active.each { |u|
if u.race == race_nr and checkunit[u]
next if caste_nr and u.caste != caste_nr
slayit[u]
count += 1
end
}
puts "#{slain} #{count} #{raw_caste} #{raw_race}"
end

@ -1,64 +1,64 @@
# script to fix loyalty cascade, when you order your militia to kill friendly units
def fixunit(unit)
return if unit.race != df.ui.race_id or unit.civ_id != df.ui.civ_id
links = unit.hist_figure_tg.entity_links
fixed = false
return if unit.race != df.ui.race_id or unit.civ_id != df.ui.civ_id
links = unit.hist_figure_tg.entity_links
fixed = false
# check if the unit is a civ renegade
if i1 = links.index { |l|
l.kind_of?(DFHack::HistfigEntityLinkFormerMemberst) and
l.entity_id == df.ui.civ_id
} and i2 = links.index { |l|
l.kind_of?(DFHack::HistfigEntityLinkEnemyst) and
l.entity_id == df.ui.civ_id
}
fixed = true
i1, i2 = i2, i1 if i1 > i2
links.delete_at i2
links.delete_at i1
links << DFHack::HistfigEntityLinkMemberst.cpp_new(:entity_id => df.ui.civ_id, :link_strength => 100)
df.add_announcement "fixloyalty: #{unit.name} is now a member of #{df.ui.civ_tg.name} again"
end
# check if the unit is a civ renegade
if i1 = links.index { |l|
l.kind_of?(DFHack::HistfigEntityLinkFormerMemberst) and
l.entity_id == df.ui.civ_id
} and i2 = links.index { |l|
l.kind_of?(DFHack::HistfigEntityLinkEnemyst) and
l.entity_id == df.ui.civ_id
}
fixed = true
i1, i2 = i2, i1 if i1 > i2
links.delete_at i2
links.delete_at i1
links << DFHack::HistfigEntityLinkMemberst.cpp_new(:entity_id => df.ui.civ_id, :link_strength => 100)
df.add_announcement "fixloyalty: #{unit.name} is now a member of #{df.ui.civ_tg.name} again"
end
# check if the unit is a group renegade
if i1 = links.index { |l|
l.kind_of?(DFHack::HistfigEntityLinkFormerMemberst) and
l.entity_id == df.ui.group_id
} and i2 = links.index { |l|
l.kind_of?(DFHack::HistfigEntityLinkEnemyst) and
l.entity_id == df.ui.group_id
}
fixed = true
i1, i2 = i2, i1 if i1 > i2
links.delete_at i2
links.delete_at i1
links << DFHack::HistfigEntityLinkMemberst.cpp_new(:entity_id => df.ui.group_id, :link_strength => 100)
df.add_announcement "fixloyalty: #{unit.name} is now a member of #{df.ui.group_tg.name} again"
end
# check if the unit is a group renegade
if i1 = links.index { |l|
l.kind_of?(DFHack::HistfigEntityLinkFormerMemberst) and
l.entity_id == df.ui.group_id
} and i2 = links.index { |l|
l.kind_of?(DFHack::HistfigEntityLinkEnemyst) and
l.entity_id == df.ui.group_id
}
fixed = true
i1, i2 = i2, i1 if i1 > i2
links.delete_at i2
links.delete_at i1
links << DFHack::HistfigEntityLinkMemberst.cpp_new(:entity_id => df.ui.group_id, :link_strength => 100)
df.add_announcement "fixloyalty: #{unit.name} is now a member of #{df.ui.group_tg.name} again"
end
# fix the 'is an enemy' cache matrix (mark to be recalculated by the game when needed)
if fixed and unit.enemy.enemy_status_slot != -1
i = unit.enemy.enemy_status_slot
unit.enemy.enemy_status_slot = -1
cache = df.world.enemy_status_cache
cache.slot_used[i] = false
cache.rel_map[i].map! { -1 }
cache.rel_map.each { |a| a[i] = -1 }
cache.next_slot = i if cache.next_slot > i
end
# fix the 'is an enemy' cache matrix (mark to be recalculated by the game when needed)
if fixed and unit.enemy.enemy_status_slot != -1
i = unit.enemy.enemy_status_slot
unit.enemy.enemy_status_slot = -1
cache = df.world.enemy_status_cache
cache.slot_used[i] = false
cache.rel_map[i].map! { -1 }
cache.rel_map.each { |a| a[i] = -1 }
cache.next_slot = i if cache.next_slot > i
end
# return true if we actually fixed the unit
fixed
# return true if we actually fixed the unit
fixed
end
count = 0
df.unit_citizens.each { |u|
count += 1 if fixunit(u)
count += 1 if fixunit(u)
}
if count > 0
puts "loyalty cascade fixed (#{count} dwarves)"
puts "loyalty cascade fixed (#{count} dwarves)"
else
puts "no loyalty cascade found"
puts "no loyalty cascade found"
end

@ -5,21 +5,21 @@
count = 0
df.world.buildings.all.each { |bld|
# for all doors
next if bld._rtti_classname != :building_doorst
# check if it is open
next if bld.close_timer == 0
# check if occupancy is set
occ = df.map_occupancy_at(bld.x1, bld.y1, bld.z)
if (occ.unit or occ.unit_grounded) and not
# check if an unit is present
df.world.units.active.find { |u| u.pos.x == bld.x1 and u.pos.y == bld.y1 and u.pos.z == bld.z }
count += 1
occ.unit = occ.unit_grounded = false
end
if occ.item and not df.world.items.all.find { |i| i.pos.x == bld.x1 and i.pos.y == bld.y1 and i.pos.z == bld.z }
count += 1
occ.item = false
end
# for all doors
next if bld._rtti_classname != :building_doorst
# check if it is open
next if bld.close_timer == 0
# check if occupancy is set
occ = df.map_occupancy_at(bld.x1, bld.y1, bld.z)
if (occ.unit or occ.unit_grounded) and not
# check if an unit is present
df.world.units.active.find { |u| u.pos.x == bld.x1 and u.pos.y == bld.y1 and u.pos.z == bld.z }
count += 1
occ.unit = occ.unit_grounded = false
end
if occ.item and not df.world.items.all.find { |i| i.pos.x == bld.x1 and i.pos.y == bld.y1 and i.pos.z == bld.z }
count += 1
occ.item = false
end
}
puts "unstuck #{count} doors"

@ -30,9 +30,9 @@ if args.help then
end
if(args.unit) then
unit = df.unit.find(args.unit)
unit = df.unit.find(args.unit)
else
unit = dfhack.gui.getSelectedUnit()
unit = dfhack.gui.getSelectedUnit()
end
if not unit then

@ -8,42 +8,42 @@ count_max = 100 if count_max == 0
@raws_plant_name ||= {}
@raws_plant_growdur ||= {}
if @raws_plant_name.empty?
df.world.raws.plants.all.each_with_index { |p, idx|
@raws_plant_name[idx] = p.id
@raws_plant_growdur[idx] = p.growdur
}
df.world.raws.plants.all.each_with_index { |p, idx|
@raws_plant_name[idx] = p.id
@raws_plant_growdur[idx] = p.growdur
}
end
inventory = Hash.new(0)
df.world.items.other[:SEEDS].each { |seed|
next if not seed.flags.in_building
next if not seed.general_refs.find { |ref| ref._rtti_classname == :general_ref_building_holderst }
next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
inventory[seed.mat_index] += 1
next if not seed.flags.in_building
next if not seed.general_refs.find { |ref| ref._rtti_classname == :general_ref_building_holderst }
next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
inventory[seed.mat_index] += 1
}
if !material or material == 'help' or material == 'list'
# show a list of available crop types
inventory.sort_by { |mat, c| c }.each { |mat, c|
name = df.world.raws.plants.all[mat].id
puts " #{name} #{c}"
}
# show a list of available crop types
inventory.sort_by { |mat, c| c }.each { |mat, c|
name = df.world.raws.plants.all[mat].id
puts " #{name} #{c}"
}
else
mat = df.match_rawname(material, inventory.keys.map { |k| @raws_plant_name[k] })
unless wantmat = @raws_plant_name.index(mat)
raise "invalid plant material #{material}"
end
mat = df.match_rawname(material, inventory.keys.map { |k| @raws_plant_name[k] })
unless wantmat = @raws_plant_name.index(mat)
raise "invalid plant material #{material}"
end
count = 0
df.world.items.other[:SEEDS].each { |seed|
next if seed.mat_index != wantmat
next if not seed.flags.in_building
next if not seed.general_refs.find { |ref| ref._rtti_classname == :general_ref_building_holderst }
next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
seed.grow_counter = @raws_plant_growdur[seed.mat_index]
count += 1
}
puts "Grown #{count} #{mat}"
count = 0
df.world.items.other[:SEEDS].each { |seed|
next if seed.mat_index != wantmat
next if not seed.flags.in_building
next if not seed.general_refs.find { |ref| ref._rtti_classname == :general_ref_building_holderst }
next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
seed.grow_counter = @raws_plant_growdur[seed.mat_index]
count += 1
}
puts "Grown #{count} #{mat}"
end

@ -31,10 +31,10 @@ function CheckCursor(p)
return true
end
function getxyz() -- this will return pointers x,y and z coordinates.
local x=df.global.cursor.x
local y=df.global.cursor.y
local z=df.global.cursor.z
return x,y,z -- return the coords
local x=df.global.cursor.x
local y=df.global.cursor.y
local z=df.global.cursor.z
return x,y,z -- return the coords
end
function GetCaste(race_id,caste_id)
@ -338,8 +338,8 @@ local cheats={
local dft=require("plugins.dfusion.tools")
for k,v in pairs(unit_list) do
dft.healunit(v)
end
return true
end
return true
end},
{name="Power up",f=function (unit_list)
local dft=require("plugins.dfusion.tools")
@ -352,16 +352,16 @@ end},
if not CheckCursor(pos) then
return false
end
adv=df.global.world.units.active[0]
item=getItemsAtPos(getxyz())[1]
print(item.id)
adv=df.global.world.units.active[0]
item=getItemsAtPos(getxyz())[1]
print(item.id)
for k,v in pairs(unit_list) do
v.riding_item_id=item.id
local ref=df.general_ref_unit_riderst:new()
ref.unit_id=v.id
item.general_refs:insert("#",ref)
end
return true
end
return true
end},
}
--[[ todo: add cheats...]]--

@ -46,7 +46,7 @@ GmEditorUi = defclass(GmEditorUi, gui.FramedScreen)
GmEditorUi.ATTRS={
frame_style = gui.GREY_LINE_FRAME,
frame_title = "GameMaster's editor",
}
}
function GmEditorUi:onHelp()
self.subviews.pages:setSelected(2)
end
@ -326,7 +326,7 @@ function GmEditorUi:updateTarget(preserve_pos,reindex)
self.subviews.lbl_current_item:itemById('name').text=tostring(trg.target)
local t={}
for k,v in pairs(trg.keys) do
table.insert(t,{text={{text=string.format("%-25s",tostring(v))},{gap=1,text=getStringValue(trg,v)}}})
table.insert(t,{text={{text=string.format("%-25s",tostring(v))},{gap=1,text=getStringValue(trg,v)}}})
end
local last_pos
if preserve_pos then

@ -111,7 +111,7 @@ function getRestrictiveMatFilter(itemType)
end
function createItem(mat,itemType,quality,creator,description)
dfhack.items.createItem(itemType[1], itemType[2], mat[1], mat[2], creator)
dfhack.items.createItem(itemType[1], itemType[2], mat[1], mat[2], creator)
if df.item_type[itemType[1]]=='SLAB' then
item.description=description
end

@ -25,13 +25,13 @@ local mod_dir=dfhack.getDFPath().."/hack/mods"
]]
function fileExists(filename)
local file=io.open(filename,"rb")
if file==nil then
return
else
file:close()
return true
end
local file=io.open(filename,"rb")
if file==nil then
return
else
file:close()
return true
end
end
if not fileExists(init_file) then
local initFile=io.open(init_file,"a")
@ -47,10 +47,10 @@ function copyFile(from,to) --oh so primitive
fileto:close()
end
function patchInit(initFileName,patch_guard,code)
local initFile=io.open(initFileName,"a")
initFile:write(string.format("\n%s\n%s\n%s",patch_guard[1],
code,patch_guard[2]))
initFile:close()
local initFile=io.open(initFileName,"a")
initFile:write(string.format("\n%s\n%s\n%s",patch_guard[1],
code,patch_guard[2]))
initFile:close()
end
function patchDofile( luaFileName,patch_guard,dofile_list,mod_path )
local luaFile=io.open(luaFileName,"a")
@ -77,89 +77,89 @@ function patchFile(file_name,patch_guard,after_string,code)
entityFile:close()
end
function findGuards(str,start,patch_guard)
local pStart=string.find(str,patch_guard[1],start)
if pStart==nil then return nil end
local pEnd=string.find(str,patch_guard[2],pStart)
if pEnd==nil then error("Start guard token found, but end was not found") end
return pStart-1,pEnd+#patch_guard[2]+1
local pStart=string.find(str,patch_guard[1],start)
if pStart==nil then return nil end
local pEnd=string.find(str,patch_guard[2],pStart)
if pEnd==nil then error("Start guard token found, but end was not found") end
return pStart-1,pEnd+#patch_guard[2]+1
end
function findGuardsFile(filename,patch_guard)
local file=io.open(filename,"r")
local buf=file:read("*all")
return findGuards(buf,1,patch_guard)
local file=io.open(filename,"r")
local buf=file:read("*all")
return findGuards(buf,1,patch_guard)
end
function unPatchFile(filename,patch_guard)
local file=io.open(filename,"r")
local buf=file:read("*all")
file:close()
local file=io.open(filename,"r")
local buf=file:read("*all")
file:close()
local newBuf=""
local pos=1
local lastPos=1
repeat
local endPos
pos,endPos=findGuards(buf,lastPos,patch_guard)
newBuf=newBuf..string.sub(buf,lastPos,pos)
if endPos~=nil then
lastPos=endPos
end
until pos==nil
local newBuf=""
local pos=1
local lastPos=1
repeat
local endPos
pos,endPos=findGuards(buf,lastPos,patch_guard)
newBuf=newBuf..string.sub(buf,lastPos,pos)
if endPos~=nil then
lastPos=endPos
end
until pos==nil
local file=io.open(filename,"w+")
file:write(newBuf)
local file=io.open(filename,"w+")
file:write(newBuf)
file:close()
end
function checkInstalled(dfMod) --try to figure out if installed
if dfMod.checkInstalled then
return dfMod.checkInstalled()
else
if dfMod.raws_list then
for k,v in pairs(dfMod.raws_list) do
if fileExists(dfhack.getDFPath().."/raw/objects/"..v) then
return true,v
end
end
end
if dfMod.patch_entity then
if findGuardsFile(entity_file,dfMod.guard)~=nil then
return true,"entity_default.txt"
end
end
if dfMod.checkInstalled then
return dfMod.checkInstalled()
else
if dfMod.raws_list then
for k,v in pairs(dfMod.raws_list) do
if fileExists(dfhack.getDFPath().."/raw/objects/"..v) then
return true,v
end
end
end
if dfMod.patch_entity then
if findGuardsFile(entity_file,dfMod.guard)~=nil then
return true,"entity_default.txt"
end
end
if dfMod.patch_files then
for k,v in pairs(dfMod.patch_files) do
if findGuardsFile(dfhack.getDFPath().."/raw/objects/"..v.filename,dfMod.guard)~=nil then
return true,"v.filename"
end
end
end
if dfMod.patch_init then
if findGuardsFile(init_file,dfMod.guard_init)~=nil then
return true,"init.lua"
end
end
end
end
if dfMod.patch_init then
if findGuardsFile(init_file,dfMod.guard_init)~=nil then
return true,"init.lua"
end
end
end
end
manager=defclass(manager,gui.FramedScreen)
function manager:init(args)
self.mods={}
local mods=self.mods
local mlist=dfhack.internal.getDir(mod_dir)
local mlist=dfhack.internal.getDir(mod_dir)
if #mlist==0 then
qerror("Mod directory not found! Are you sure it is in:"..mod_dir)
end
for k,v in ipairs(mlist) do
if v~="." and v~=".." then
local f,modData=pcall(dofile,mod_dir.."/".. v .. "/init.lua")
for k,v in ipairs(mlist) do
if v~="." and v~=".." then
local f,modData=pcall(dofile,mod_dir.."/".. v .. "/init.lua")
if f then
mods[modData.name]=modData
modData.guard=modData.guard or {">>"..modData.name.." patch","<<End "..modData.name.." patch"}
modData.guard_init={"--"..modData.guard[1],"--"..modData.guard[2]}
modData.path=mod_dir.."/"..v..'/'
end
end
end
end
end
---show thingy
local modList={}
for k,v in pairs(self.mods) do
@ -270,29 +270,29 @@ function manager:install(trgMod,force)
local isInstalled,file=checkInstalled(trgMod) -- maybe load from .installed?
if isInstalled then
qerror("Mod already installed. File:"..file)
end
end
end
print("installing:"..trgMod.name)
if trgMod.pre_install then
trgMod.pre_install(args)
end
if trgMod.raws_list then
for k,v in pairs(trgMod.raws_list) do
copyFile(trgMod.path..v,dfhack.getDFPath().."/raw/objects/"..v)
end
end
if trgMod.patch_entity then
local entity_target="[ENTITY:MOUNTAIN]" --TODO configure
patchFile(entity_file,trgMod.guard,entity_target,trgMod.patch_entity)
end
if trgMod.raws_list then
for k,v in pairs(trgMod.raws_list) do
copyFile(trgMod.path..v,dfhack.getDFPath().."/raw/objects/"..v)
end
end
if trgMod.patch_entity then
local entity_target="[ENTITY:MOUNTAIN]" --TODO configure
patchFile(entity_file,trgMod.guard,entity_target,trgMod.patch_entity)
end
if trgMod.patch_files then
for k,v in pairs(trgMod.patch_files) do
patchFile(dfhack.getDFPath().."/raw/objects/"..v.filename,trgMod.guard,v.after,v.patch)
end
end
if trgMod.patch_init then
patchInit(init_file,trgMod.guard_init,trgMod.patch_init)
end
if trgMod.patch_init then
patchInit(init_file,trgMod.guard_init,trgMod.patch_init)
end
if trgMod.patch_dofile then
patchDofile(init_file,trgMod.guard_init,trgMod.patch_dofile,trgMod.path)
end
@ -305,29 +305,29 @@ function manager:install(trgMod,force)
end
function manager:uninstall(trgMod)
print("Uninstalling:"..trgMod.name)
if trgMod.pre_uninstall then
if trgMod.pre_uninstall then
trgMod.pre_uninstall(args)
end
if trgMod.raws_list then
for k,v in pairs(trgMod.raws_list) do
os.remove(dfhack.getDFPath().."/raw/objects/"..v)
end
end
if trgMod.patch_entity then
unPatchFile(entity_file,trgMod.guard)
end
if trgMod.raws_list then
for k,v in pairs(trgMod.raws_list) do
os.remove(dfhack.getDFPath().."/raw/objects/"..v)
end
end
if trgMod.patch_entity then
unPatchFile(entity_file,trgMod.guard)
end
if trgMod.patch_files then
for k,v in pairs(trgMod.patch_files) do
unPatchFile(dfhack.getDFPath().."/raw/objects/"..v.filename,trgMod.guard)
end
end
if trgMod.patch_init or trgMod.patch_dofile then
unPatchFile(init_file,trgMod.guard_init)
end
if trgMod.patch_init or trgMod.patch_dofile then
unPatchFile(init_file,trgMod.guard_init)
end
trgMod.installed=false
if trgMod.post_uninstall then
if trgMod.post_uninstall then
trgMod.post_uninstall(args)
end
print("done")

@ -1,78 +1,78 @@
# control your levers from the dfhack console
def lever_pull_job(bld)
ref = DFHack::GeneralRefBuildingHolderst.cpp_new
ref.building_id = bld.id
ref = DFHack::GeneralRefBuildingHolderst.cpp_new
ref.building_id = bld.id
job = DFHack::Job.cpp_new
job.job_type = :PullLever
job.pos = [bld.centerx, bld.centery, bld.z]
job.general_refs << ref
bld.jobs << job
df.job_link job
job = DFHack::Job.cpp_new
job.job_type = :PullLever
job.pos = [bld.centerx, bld.centery, bld.z]
job.general_refs << ref
bld.jobs << job
df.job_link job
puts lever_descr(bld)
puts lever_descr(bld)
end
def lever_pull_cheat(bld)
bld.linked_mechanisms.each { |i|
i.general_refs.grep(DFHack::GeneralRefBuildingHolderst).each { |r|
r.building_tg.setTriggerState(bld.state)
}
}
bld.linked_mechanisms.each { |i|
i.general_refs.grep(DFHack::GeneralRefBuildingHolderst).each { |r|
r.building_tg.setTriggerState(bld.state)
}
}
bld.state = (bld.state == 0 ? 1 : 0)
bld.state = (bld.state == 0 ? 1 : 0)
puts lever_descr(bld)
puts lever_descr(bld)
end
def lever_descr(bld, idx=nil)
ret = []
# lever description
descr = ''
descr << "#{idx}: " if idx
descr << "lever ##{bld.id} @[#{bld.centerx}, #{bld.centery}, #{bld.z}] #{bld.state == 0 ? '\\' : '/'}"
bld.jobs.each { |j|
if j.job_type == :PullLever
flags = ''
flags << ', repeat' if j.flags.repeat
flags << ', suspended' if j.flags.suspend
descr << " (pull order#{flags})"
end
}
bld.linked_mechanisms.map { |i|
i.general_refs.grep(DFHack::GeneralRefBuildingHolderst)
}.flatten.each { |r|
# linked building description
tg = r.building_tg
state = ''
if tg.respond_to?(:gate_flags)
state << (tg.gate_flags.closed ? 'closed' : 'opened')
state << ", closing (#{tg.timer})" if tg.gate_flags.closing
state << ", opening (#{tg.timer})" if tg.gate_flags.opening
end
ret << (descr + " linked to #{tg._rtti_classname} ##{tg.id} @[#{tg.centerx}, #{tg.centery}, #{tg.z}] #{state}")
# indent other links
descr = descr.gsub(/./, ' ')
}
ret << descr if ret.empty?
ret
ret = []
# lever description
descr = ''
descr << "#{idx}: " if idx
descr << "lever ##{bld.id} @[#{bld.centerx}, #{bld.centery}, #{bld.z}] #{bld.state == 0 ? '\\' : '/'}"
bld.jobs.each { |j|
if j.job_type == :PullLever
flags = ''
flags << ', repeat' if j.flags.repeat
flags << ', suspended' if j.flags.suspend
descr << " (pull order#{flags})"
end
}
bld.linked_mechanisms.map { |i|
i.general_refs.grep(DFHack::GeneralRefBuildingHolderst)
}.flatten.each { |r|
# linked building description
tg = r.building_tg
state = ''
if tg.respond_to?(:gate_flags)
state << (tg.gate_flags.closed ? 'closed' : 'opened')
state << ", closing (#{tg.timer})" if tg.gate_flags.closing
state << ", opening (#{tg.timer})" if tg.gate_flags.opening
end
ret << (descr + " linked to #{tg._rtti_classname} ##{tg.id} @[#{tg.centerx}, #{tg.centery}, #{tg.z}] #{state}")
# indent other links
descr = descr.gsub(/./, ' ')
}
ret << descr if ret.empty?
ret
end
def lever_list
@lever_list = []
df.world.buildings.other[:TRAP].find_all { |bld|
bld.trap_type == :Lever
}.sort_by { |bld| bld.id }.each { |bld|
puts lever_descr(bld, @lever_list.length)
@lever_list << bld.id
}
@lever_list = []
df.world.buildings.other[:TRAP].find_all { |bld|
bld.trap_type == :Lever
}.sort_by { |bld| bld.id }.each { |bld|
puts lever_descr(bld, @lever_list.length)
@lever_list << bld.id
}
end
@ -80,33 +80,33 @@ end
case $script_args[0]
when 'pull'
cheat = $script_args.delete('--cheat') || $script_args.delete('--now')
cheat = $script_args.delete('--cheat') || $script_args.delete('--now')
id = $script_args[1].to_i
id = @lever_list[id] || id
bld = df.building_find(id)
raise 'invalid lever id' if not bld
id = $script_args[1].to_i
id = @lever_list[id] || id
bld = df.building_find(id)
raise 'invalid lever id' if not bld
if cheat
lever_pull_cheat(bld)
else
lever_pull_job(bld)
end
if cheat
lever_pull_cheat(bld)
else
lever_pull_job(bld)
end
when 'list'
lever_list
lever_list
when /^\d+$/
id = $script_args[0].to_i
id = @lever_list[id] || id
bld = df.building_find(id)
raise 'invalid lever id' if not bld
id = $script_args[0].to_i
id = @lever_list[id] || id
bld = df.building_find(id)
raise 'invalid lever id' if not bld
puts lever_descr(bld)
puts lever_descr(bld)
else
puts <<EOS
puts <<EOS
Lever control from the dfhack console
Usage:

@ -20,10 +20,10 @@ def find_all_ore_veins
}
df.onstatechange_register_once { |st|
if st == :MAP_LOADED
$ore_veins = nil # invalidate veins cache
true
end
if st == :MAP_LOADED
$ore_veins = nil # invalidate veins cache
true
end
}
$ore_veins

@ -2,39 +2,39 @@
case $script_args[0]
when '?', 'help'
puts <<EOS
puts <<EOS
Run this script with the cursor on top of a pit/pond activity zone, or with a zone identifier as argument.
It will mark all caged creatures on tiles covered by the zone to be dumped.
Works best with an animal stockpile on top of the pit/pond zone.
EOS
throw :script_finished
throw :script_finished
when /(\d+)/
nr = $1.to_i
bld = df.world.buildings.other[:ACTIVITY_ZONE].find { |zone| zone.zone_num == nr }
nr = $1.to_i
bld = df.world.buildings.other[:ACTIVITY_ZONE].find { |zone| zone.zone_num == nr }
else
bld = df.world.buildings.other[:ACTIVITY_ZONE].find { |zone|
zone.zone_flags.pit_pond and zone.z == df.cursor.z and
zone.x1 <= df.cursor.x and zone.x2 >= df.cursor.x and zone.y1 <= df.cursor.y and zone.y2 >= df.cursor.y
}
bld = df.world.buildings.other[:ACTIVITY_ZONE].find { |zone|
zone.zone_flags.pit_pond and zone.z == df.cursor.z and
zone.x1 <= df.cursor.x and zone.x2 >= df.cursor.x and zone.y1 <= df.cursor.y and zone.y2 >= df.cursor.y
}
end
if not bld
puts "Please select a pit/pond zone"
throw :script_finished
puts "Please select a pit/pond zone"
throw :script_finished
end
found = 0
df.world.items.other[:CAGE].each { |cg|
next if not cg.flags.on_ground
next if cg.pos.z != bld.z or cg.pos.x < bld.x1 or cg.pos.x > bld.x2 or cg.pos.y < bld.y1 or cg.pos.y > bld.y2
next if not uref = cg.general_refs.grep(DFHack::GeneralRefContainsUnitst).first
found += 1
u = uref.unit_tg
puts "Pitting #{u.race_tg.name[0]} #{u.id} #{u.name}"
u.general_refs << DFHack::GeneralRefBuildingCivzoneAssignedst.cpp_new(:building_id => bld.id)
bld.assigned_units << u.id
next if not cg.flags.on_ground
next if cg.pos.z != bld.z or cg.pos.x < bld.x1 or cg.pos.x > bld.x2 or cg.pos.y < bld.y1 or cg.pos.y > bld.y2
next if not uref = cg.general_refs.grep(DFHack::GeneralRefContainsUnitst).first
found += 1
u = uref.unit_tg
puts "Pitting #{u.race_tg.name[0]} #{u.id} #{u.name}"
u.general_refs << DFHack::GeneralRefBuildingCivzoneAssignedst.cpp_new(:building_id => bld.id)
bld.assigned_units << u.id
}
puts "No creature available for pitting" if found == 0

@ -3,73 +3,73 @@
$sources ||= []
cur_source = {
:liquid => 'water',
:amount => 7,
:pos => [df.cursor.x, df.cursor.y, df.cursor.z]
:liquid => 'water',
:amount => 7,
:pos => [df.cursor.x, df.cursor.y, df.cursor.z]
}
cmd = 'help'
$script_args.each { |a|
case a.downcase
when 'water', 'magma'
cur_source[:liquid] = a.downcase
when /^\d+$/
cur_source[:amount] = a.to_i
when 'add', 'del', 'delete', 'clear', 'help', 'list'
cmd = a.downcase
else
puts "source: unhandled argument #{a}"
end
case a.downcase
when 'water', 'magma'
cur_source[:liquid] = a.downcase
when /^\d+$/
cur_source[:amount] = a.to_i
when 'add', 'del', 'delete', 'clear', 'help', 'list'
cmd = a.downcase
else
puts "source: unhandled argument #{a}"
end
}
case cmd
when 'add'
$sources_onupdate ||= df.onupdate_register('sources', 12) {
# called every 12 game ticks (100x a dwarf day)
$sources.each { |s|
if tile = df.map_tile_at(*s[:pos]) and tile.shape_passableflow
# XXX does not check current liquid_type
des = tile.designation
cur = des.flow_size
if cur != s[:amount]
tile.spawn_liquid((cur > s[:amount] ? cur-1 : cur+1), s[:liquid] == 'magma')
end
end
}
if $sources.empty?
df.onupdate_unregister($sources_onupdate)
$sources_onupdate = nil
end
}
$sources_onupdate ||= df.onupdate_register('sources', 12) {
# called every 12 game ticks (100x a dwarf day)
$sources.each { |s|
if tile = df.map_tile_at(*s[:pos]) and tile.shape_passableflow
# XXX does not check current liquid_type
des = tile.designation
cur = des.flow_size
if cur != s[:amount]
tile.spawn_liquid((cur > s[:amount] ? cur-1 : cur+1), s[:liquid] == 'magma')
end
end
}
if $sources.empty?
df.onupdate_unregister($sources_onupdate)
$sources_onupdate = nil
end
}
if cur_source[:pos][0] >= 0
if tile = df.map_tile_at(*cur_source[:pos])
if tile.shape_passableflow
$sources << cur_source
else
puts "Impassable tile: I'm afraid I can't do that, Dave"
end
else
puts "Unallocated map block - build something here first"
end
else
puts "Please put the game cursor where you want a source"
end
if cur_source[:pos][0] >= 0
if tile = df.map_tile_at(*cur_source[:pos])
if tile.shape_passableflow
$sources << cur_source
else
puts "Impassable tile: I'm afraid I can't do that, Dave"
end
else
puts "Unallocated map block - build something here first"
end
else
puts "Please put the game cursor where you want a source"
end
when 'del', 'delete'
$sources.delete_if { |s| s[:pos] == cur_source[:pos] }
$sources.delete_if { |s| s[:pos] == cur_source[:pos] }
when 'clear'
$sources.clear
$sources.clear
when 'list'
puts "Source list:", $sources.map { |s|
" #{s[:pos].inspect} #{s[:liquid]} #{s[:amount]}"
}
puts "Current cursor pos: #{[df.cursor.x, df.cursor.y, df.cursor.z].inspect}" if df.cursor.x >= 0
puts "Source list:", $sources.map { |s|
" #{s[:pos].inspect} #{s[:liquid]} #{s[:amount]}"
}
puts "Current cursor pos: #{[df.cursor.x, df.cursor.y, df.cursor.z].inspect}" if df.cursor.x >= 0
else
puts <<EOS
puts <<EOS
Creates a new infinite liquid source at the cursor.
Examples:

@ -1,185 +1,185 @@
# mark stuff inside of cages for dumping.
def plural(nr, name)
# '1 cage' / '4 cages'
"#{nr} #{name}#{'s' if nr > 1}"
# '1 cage' / '4 cages'
"#{nr} #{name}#{'s' if nr > 1}"
end
def cage_dump_items(list)
count = 0
count_cage = 0
list.each { |cage|
pre_count = count
cage.general_refs.each { |ref|
next unless ref.kind_of?(DFHack::GeneralRefContainsItemst)
next if ref.item_tg.flags.dump
count += 1
ref.item_tg.flags.dump = true
}
count_cage += 1 if pre_count != count
}
puts "Dumped #{plural(count, 'item')} in #{plural(count_cage, 'cage')}"
count = 0
count_cage = 0
list.each { |cage|
pre_count = count
cage.general_refs.each { |ref|
next unless ref.kind_of?(DFHack::GeneralRefContainsItemst)
next if ref.item_tg.flags.dump
count += 1
ref.item_tg.flags.dump = true
}
count_cage += 1 if pre_count != count
}
puts "Dumped #{plural(count, 'item')} in #{plural(count_cage, 'cage')}"
end
def cage_dump_armor(list)
count = 0
count_cage = 0
list.each { |cage|
pre_count = count
cage.general_refs.each { |ref|
next unless ref.kind_of?(DFHack::GeneralRefContainsUnitst)
ref.unit_tg.inventory.each { |it|
next if it.mode != :Worn
next if it.item.flags.dump
count += 1
it.item.flags.dump = true
}
}
count_cage += 1 if pre_count != count
}
puts "Dumped #{plural(count, 'armor piece')} in #{plural(count_cage, 'cage')}"
count = 0
count_cage = 0
list.each { |cage|
pre_count = count
cage.general_refs.each { |ref|
next unless ref.kind_of?(DFHack::GeneralRefContainsUnitst)
ref.unit_tg.inventory.each { |it|
next if it.mode != :Worn
next if it.item.flags.dump
count += 1
it.item.flags.dump = true
}
}
count_cage += 1 if pre_count != count
}
puts "Dumped #{plural(count, 'armor piece')} in #{plural(count_cage, 'cage')}"
end
def cage_dump_weapons(list)
count = 0
count_cage = 0
list.each { |cage|
pre_count = count
cage.general_refs.each { |ref|
next unless ref.kind_of?(DFHack::GeneralRefContainsUnitst)
ref.unit_tg.inventory.each { |it|
next if it.mode != :Weapon
next if it.item.flags.dump
count += 1
it.item.flags.dump = true
}
}
count_cage += 1 if pre_count != count
}
puts "Dumped #{plural(count, 'weapon')} in #{plural(count_cage, 'cage')}"
count = 0
count_cage = 0
list.each { |cage|
pre_count = count
cage.general_refs.each { |ref|
next unless ref.kind_of?(DFHack::GeneralRefContainsUnitst)
ref.unit_tg.inventory.each { |it|
next if it.mode != :Weapon
next if it.item.flags.dump
count += 1
it.item.flags.dump = true
}
}
count_cage += 1 if pre_count != count
}
puts "Dumped #{plural(count, 'weapon')} in #{plural(count_cage, 'cage')}"
end
def cage_dump_all(list)
count = 0
count_cage = 0
list.each { |cage|
pre_count = count
cage.general_refs.each { |ref|
case ref
when DFHack::GeneralRefContainsItemst
next if ref.item_tg.flags.dump
count += 1
ref.item_tg.flags.dump = true
when DFHack::GeneralRefContainsUnitst
ref.unit_tg.inventory.each { |it|
next if it.item.flags.dump
count += 1
it.item.flags.dump = true
}
end
}
count_cage += 1 if pre_count != count
}
puts "Dumped #{plural(count, 'item')} in #{plural(count_cage, 'cage')}"
count = 0
count_cage = 0
list.each { |cage|
pre_count = count
cage.general_refs.each { |ref|
case ref
when DFHack::GeneralRefContainsItemst
next if ref.item_tg.flags.dump
count += 1
ref.item_tg.flags.dump = true
when DFHack::GeneralRefContainsUnitst
ref.unit_tg.inventory.each { |it|
next if it.item.flags.dump
count += 1
it.item.flags.dump = true
}
end
}
count_cage += 1 if pre_count != count
}
puts "Dumped #{plural(count, 'item')} in #{plural(count_cage, 'cage')}"
end
def cage_dump_list(list)
count_total = Hash.new(0)
empty_cages = 0
list.each { |cage|
count = Hash.new(0)
cage.general_refs.each { |ref|
case ref
when DFHack::GeneralRefContainsItemst
count[ref.item_tg._rtti_classname] += 1
when DFHack::GeneralRefContainsUnitst
ref.unit_tg.inventory.each { |it|
count[it.item._rtti_classname] += 1
}
# TODO vermin ?
else
puts "unhandled ref #{ref.inspect}" if $DEBUG
end
}
type = case cage
when DFHack::ItemCagest; 'Cage'
when DFHack::ItemAnimaltrapst; 'Animal trap'
else cage._rtti_classname
end
if count.empty?
empty_cages += 1
else
puts "#{type} ##{cage.id}: ", count.sort_by { |k, v| v }.map { |k, v| " #{v} #{k}" }
end
count.each { |k, v| count_total[k] += v }
}
if list.length > 2
puts '', "Total: ", count_total.sort_by { |k, v| v }.map { |k, v| " #{v} #{k}" }
puts "with #{plural(empty_cages, 'empty cage')}"
end
count_total = Hash.new(0)
empty_cages = 0
list.each { |cage|
count = Hash.new(0)
cage.general_refs.each { |ref|
case ref
when DFHack::GeneralRefContainsItemst
count[ref.item_tg._rtti_classname] += 1
when DFHack::GeneralRefContainsUnitst
ref.unit_tg.inventory.each { |it|
count[it.item._rtti_classname] += 1
}
# TODO vermin ?
else
puts "unhandled ref #{ref.inspect}" if $DEBUG
end
}
type = case cage
when DFHack::ItemCagest; 'Cage'
when DFHack::ItemAnimaltrapst; 'Animal trap'
else cage._rtti_classname
end
if count.empty?
empty_cages += 1
else
puts "#{type} ##{cage.id}: ", count.sort_by { |k, v| v }.map { |k, v| " #{v} #{k}" }
end
count.each { |k, v| count_total[k] += v }
}
if list.length > 2
puts '', "Total: ", count_total.sort_by { |k, v| v }.map { |k, v| " #{v} #{k}" }
puts "with #{plural(empty_cages, 'empty cage')}"
end
end
# handle magic script arguments
here_only = $script_args.delete 'here'
if here_only
it = df.item_find
list = [it]
if not it.kind_of?(DFHack::ItemCagest) and not it.kind_of?(DFHack::ItemAnimaltrapst)
list = df.world.items.other[:ANY_CAGE_OR_TRAP].find_all { |i| df.at_cursor?(i) }
end
if list.empty?
puts 'Please select a cage'
throw :script_finished
end
it = df.item_find
list = [it]
if not it.kind_of?(DFHack::ItemCagest) and not it.kind_of?(DFHack::ItemAnimaltrapst)
list = df.world.items.other[:ANY_CAGE_OR_TRAP].find_all { |i| df.at_cursor?(i) }
end
if list.empty?
puts 'Please select a cage'
throw :script_finished
end
elsif ids = $script_args.find_all { |arg| arg =~ /^\d+$/ } and ids.first
list = []
ids.each { |id|
$script_args.delete id
if not it = df.item_find(id.to_i)
puts "Invalid item id #{id}"
elsif not it.kind_of?(DFHack::ItemCagest) and not it.kind_of?(DFHack::ItemAnimaltrapst)
puts "Item ##{id} is not a cage"
list << it
else
list << it
end
}
if list.empty?
puts 'Please use a valid cage id'
throw :script_finished
end
list = []
ids.each { |id|
$script_args.delete id
if not it = df.item_find(id.to_i)
puts "Invalid item id #{id}"
elsif not it.kind_of?(DFHack::ItemCagest) and not it.kind_of?(DFHack::ItemAnimaltrapst)
puts "Item ##{id} is not a cage"
list << it
else
list << it
end
}
if list.empty?
puts 'Please use a valid cage id'
throw :script_finished
end
else
list = df.world.items.other[:ANY_CAGE_OR_TRAP]
list = df.world.items.other[:ANY_CAGE_OR_TRAP]
end
# act
case $script_args[0]
when /^it/i
cage_dump_items(list)
cage_dump_items(list)
when /^arm/i
cage_dump_armor(list)
cage_dump_armor(list)
when /^wea/i
cage_dump_weapons(list)
cage_dump_weapons(list)
when 'all'
cage_dump_all(list)
cage_dump_all(list)
when 'list'
cage_dump_list(list)
cage_dump_list(list)
else
puts <<EOS
puts <<EOS
Marks items inside all cages for dumping.
Add 'here' to dump stuff only for selected cage.
Add a cage id to dump stuff for this cage only.

@ -5,72 +5,72 @@ $superdwarf_ids ||= []
case $script_args[0]
when 'add'
if u = df.unit_find
$superdwarf_ids |= [u.id]
if u = df.unit_find
$superdwarf_ids |= [u.id]
$superdwarf_onupdate ||= df.onupdate_register('superdwarf', 1) {
if $superdwarf_ids.empty?
df.onupdate_unregister($superdwarf_onupdate)
$superdwarf_onupdate = nil
else
$superdwarf_ids.each { |id|
if u = df.unit_find(id) and not u.flags1.dead
u.actions.each { |a|
case a.type
when :Move
a.data.move.timer = 1
when :Climb
a.data.climb.timer = 1
when :Job
a.data.job.timer = 1
when :Job2
a.data.job2.timer = 1
when :Attack
# Attack execution timer; fires when reaches zero.
a.data.attack.timer1 = 1
# Attack completion timer: finishes action at zero.
# An action must complete before target re-seleciton
# occurs.
a.data.attack.timer2 = 0
end
}
$superdwarf_onupdate ||= df.onupdate_register('superdwarf', 1) {
if $superdwarf_ids.empty?
df.onupdate_unregister($superdwarf_onupdate)
$superdwarf_onupdate = nil
else
$superdwarf_ids.each { |id|
if u = df.unit_find(id) and not u.flags1.dead
u.actions.each { |a|
case a.type
when :Move
a.data.move.timer = 1
when :Climb
a.data.climb.timer = 1
when :Job
a.data.job.timer = 1
when :Job2
a.data.job2.timer = 1
when :Attack
# Attack execution timer; fires when reaches zero.
a.data.attack.timer1 = 1
# Attack completion timer: finishes action at zero.
# An action must complete before target re-seleciton
# occurs.
a.data.attack.timer2 = 0
end
}
# no sleep
if u.counters2.sleepiness_timer > 10000
u.counters2.sleepiness_timer = 1
end
# no sleep
if u.counters2.sleepiness_timer > 10000
u.counters2.sleepiness_timer = 1
end
# no break
if b = u.status.misc_traits.find { |t| t.id == :OnBreak }
b.value = 500_000
end
else
$superdwarf_ids.delete id
end
}
end
}
else
puts "Select a creature using 'v'"
end
# no break
if b = u.status.misc_traits.find { |t| t.id == :OnBreak }
b.value = 500_000
end
else
$superdwarf_ids.delete id
end
}
end
}
else
puts "Select a creature using 'v'"
end
when 'del'
if u = df.unit_find
$superdwarf_ids.delete u.id
else
puts "Select a creature using 'v'"
end
if u = df.unit_find
$superdwarf_ids.delete u.id
else
puts "Select a creature using 'v'"
end
when 'clear'
$superdwarf_ids.clear
$superdwarf_ids.clear
when 'list'
puts "current superdwarves:", $superdwarf_ids.map { |id| df.unit_find(id).name }
puts "current superdwarves:", $superdwarf_ids.map { |id| df.unit_find(id).name }
else
puts "Usage:",
" - superdwarf add: give superspeed to currently selected creature",
" - superdwarf del: remove superspeed to current creature",
" - superdwarf clear: remove all superpowers",
" - superdwarf list: list super-dwarves"
puts "Usage:",
" - superdwarf add: give superspeed to currently selected creature",
" - superdwarf del: remove superspeed to current creature",
" - superdwarf clear: remove all superpowers",
" - superdwarf list: list super-dwarves"
end

@ -2,16 +2,16 @@ joblist = df.world.job_list.next
count = 0
while joblist
job = joblist.item
joblist = joblist.next
job = joblist.item
joblist = joblist.next
if job.job_type == :ConstructBuilding
if (job.flags.suspend && job.items && job.items[0])
item = job.items[0].item
job.flags.suspend = false
count += 1
end
end
if job.job_type == :ConstructBuilding
if (job.flags.suspend && job.items && job.items[0])
item = job.items[0].item
job.flags.suspend = false
count += 1
end
end
end
puts "Unsuspended #{count} job(s)."

@ -0,0 +1,122 @@
import re, os, sys
valid_extensions = ['c', 'cpp', 'h', 'hpp', 'mm', 'lua', 'rb', 'proto',
'init', 'init-example']
path_blacklist = [
'library/include/df/',
'plugins/stonesense/allegro',
'plugins/isoworld/allegro',
'plugins/isoworld/agui',
'depends/',
'.git/',
'build',
]
def valid_file(filename):
return len(filter(lambda ext: filename.endswith('.' + ext), valid_extensions)) and \
not len(filter(lambda path: path.replace('\\', '/') in filename.replace('\\', '/'), path_blacklist))
success = True
def error(msg):
global success
success = False
sys.stderr.write(msg + '\n')
class LinterError(Exception): pass
class Linter(object):
def check(self, lines):
failures = []
for i, line in enumerate(lines):
if not self.check_line(line):
failures.append(i + 1)
if len(failures):
raise LinterError('%s: %s' % (self.msg, self.display_lines(failures, len(lines))))
def fix(self, lines):
for i in range(len(lines)):
lines[i] = self.fix_line(lines[i])
def display_lines(self, lines, total):
if len(lines) == total - 1:
return 'entire file'
if not len(lines):
# should never happen
return 'nowhere'
if len(lines) == 1:
return 'line %i' % lines[0]
s = 'lines '
range_start = range_end = lines[0]
for i, line in enumerate(lines):
if line > range_end + 1:
if range_start == range_end:
s += ('%i, ' % range_end)
else:
s += ('%i-%i, ' % (range_start, range_end))
range_start = range_end = line
if i == len(lines) - 1:
s += ('%i' % line)
else:
range_end = line
if i == len(lines) - 1:
s += ('%i-%i, ' % (range_start, range_end))
return s.rstrip(' ').rstrip(',')
class NewlineLinter(Linter):
msg = 'Contains DOS-style newlines'
def check_line(self, line):
return '\r' not in line
def fix_line(self, line):
return line.replace('\r', '')
class TrailingWhitespaceLinter(Linter):
msg = 'Contains trailing whitespace'
def check_line(self, line):
line = line.replace('\r', '')
return not line.endswith(' ') and not line.endswith('\t')
def fix_line(self, line):
return line.rstrip('\t ')
class TabLinter(Linter):
msg = 'Contains tabs'
def check_line(self, line):
return '\t' not in line
def fix_line(self, line):
return line.replace('\t', ' ')
linters = [NewlineLinter(), TrailingWhitespaceLinter(), TabLinter()]
def main():
root_path = os.path.abspath(sys.argv[1] if len(sys.argv) > 1 else '.')
fix = (len(sys.argv) > 2 and sys.argv[2] == '--fix')
global path_blacklist
path_blacklist = map(lambda s: os.path.join(root_path, s), path_blacklist)
for cur, dirnames, filenames in os.walk(root_path):
for filename in filenames:
full_path = os.path.join(cur, filename)
rel_path = full_path.replace(root_path, '.')
if not valid_file(full_path):
continue
lines = []
with open(full_path, 'rb') as f:
lines = f.read().split('\n')
for linter in linters:
try:
linter.check(lines)
except LinterError as e:
error('%s: %s' % (rel_path, e))
if fix:
linter.fix(lines)
contents = '\n'.join(lines)
with open(full_path, 'wb') as f:
f.write(contents)
if success:
print('All linters completed successfully')
sys.exit(0)
else:
sys.exit(1)
if __name__ == '__main__':
main()

@ -0,0 +1,29 @@
import json, os, sys
if sys.version.startswith('2'):
from urllib2 import urlopen, HTTPError
else:
from urllib.request import urlopen
from urllib.error import HTTPError
try:
pr_id = int(os.environ.get('TRAVIS_PULL_REQUEST', 'false'))
except ValueError:
print('Not a pull request')
sys.exit(0)
print('Pull request %i' % pr_id)
res = {}
try:
res = json.loads(urlopen('https://api.github.com/repos/dfhack/dfhack/pulls/%i' % pr_id).read().decode('utf-8'))
except ValueError:
pass
except HTTPError:
print('Failed to retrieve PR information from API')
sys.exit(2)
if 'base' not in res or 'ref' not in res['base']:
print('Invalid JSON returned from API')
sys.exit(2)
if res['base']['ref'] != 'develop':
print('Not based on develop branch')
sys.exit(1)
else:
print('Ok')
sys.exit(0)