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

@ -143,7 +143,7 @@ DFhackCExport uint32_t SDL_GetTicks(void)
/***** Surfaces
SDL_CreateRGBSurface
SDL_Surface * SDLCALL SDL_CreateRGBSurface
(Uint32 flags, int width, int height, int depth,
(Uint32 flags, int width, int height, int depth,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
SDL_CreateRGBSurfaceFrom
@ -216,7 +216,7 @@ SDL_SaveBMP_RW
SDL_SetAlpha
int SDLCALL SDL_SetAlpha(SDL_Surface *surface, Uint32 flag, Uint8 alpha);
SDL_SetColorKey
int SDLCALL SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key);
@ -311,16 +311,16 @@ DFhackCExport int SDL_UpperBlit(DFHack::DFSDL_Surface* src, DFHack::DFSDL_Rect*
/***** Even more surface
SDL_GL_GetAttribute
int SDLCALL SDL_GL_GetAttribute(SDL_GLattr attr, int* value);
SDL_GL_SetAttribute
int SDLCALL SDL_GL_SetAttribute(SDL_GLattr attr, int value);
SDL_WM_SetCaption
void SDLCALL SDL_WM_SetCaption(const char *title, const char *icon);
SDL_WM_SetIcon
void SDLCALL SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask);
SDL_FillRect
int SDLCALL SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
*/
@ -787,7 +787,7 @@ bool FirstCall()
_SDL_mutexP = (int (*)(vPtr))GetProcAddress(realSDLlib,"SDL_mutexP");
_SDL_mutexV = (int (*)(vPtr))GetProcAddress(realSDLlib,"SDL_mutexV");
_SDL_strlcpy = (size_t (*)(char*, const char*, size_t))GetProcAddress(realSDLlib,"SDL_strlcpy");
// stuff for SDL_Image
_SDL_ClearError = (void (*)())GetProcAddress(realSDLlib,"SDL_ClearError");
_SDL_Error = (void (*)(int))GetProcAddress(realSDLlib,"SDL_Error");
@ -799,7 +799,7 @@ bool FirstCall()
_SDL_SetError = (void (*)(const char*, ...))GetProcAddress(realSDLlib,"SDL_SetError");
_SDL_UnloadObject = (void (*)(vPtr))GetProcAddress(realSDLlib,"SDL_UnloadObject");
_SDL_FillRect = (int (*)(void*,void*,uint32_t))GetProcAddress(realSDLlib,"SDL_FillRect");
// new in DF 0.31.04
_SDL_CreateSemaphore = (void* (*)(uint32_t))GetProcAddress(realSDLlib,"SDL_CreateSemaphore");
_SDL_CreateThread = (vPtr (*)(int (*fn)(void *), void *data))GetProcAddress(realSDLlib,"SDL_CreateThread");
@ -812,7 +812,7 @@ bool FirstCall()
_SDL_SemTryWait = (int (*)(void *))GetProcAddress(realSDLlib,"SDL_SemTryWait");
_SDL_SemWait = (int (*)(void *))GetProcAddress(realSDLlib,"SDL_SemWait");
_SDL_ThreadID = (uint32_t (*)(void))GetProcAddress(realSDLlib,"SDL_ThreadID");
_SDL_EnableUNICODE(1);
fprintf(stderr,"Initized HOOKS!\n");

@ -345,7 +345,7 @@ namespace DFHack
bool is_direct_instance(virtual_ptr instance_ptr) {
if (!instance_ptr) return false;
return vtable_ptr ? (vtable_ptr == get_vtable(instance_ptr))
return vtable_ptr ? (vtable_ptr == get_vtable(instance_ptr))
: (this == get(instance_ptr));
}

@ -42,7 +42,7 @@ distribution.
/**
* [peterix@peterix dfhack]$ man wcscpy_s
* No manual entry for wcscpy_s
*
*
* Proprietary extensions.
*/
// disable stupid

@ -78,7 +78,7 @@ namespace SDL
K_GREATER = 62,
K_QUESTION = 63,
K_AT = 64,
/*
/*
Skip uppercase letters
*/
K_LEFTBRACKET = 91,

@ -335,7 +335,7 @@ namespace DFHack
* zilpin: Find a tile type similar to the one given, but with a different class.
* Useful for tile-editing operations.
* If no match found, returns the sourceType
*
*
* @todo Definitely needs improvement for wall directions, etc.
*/
DFHACK_EXPORT df::tiletype findSimilarTileType( const df::tiletype sourceTileType, const df::tiletype_shape tshape );

@ -193,14 +193,14 @@ void clearBuildings(color_ostream& out);
/**
* Iterates over the items stored on a stockpile.
* (For stockpiles with containers, yields the containers, not their contents.)
*
*
* Usage:
*
*
* Buildings::StockpileIterator stored;
* for (stored.begin(stockpile); !stored.done(); ++stored) {
* df::item *item = *stored;
* }
*
*
* Implementation detail: Uses tile blocks for speed.
* For each tile block that contains at least part of the stockpile,
* starting at the top left and moving right, row by row,
@ -212,14 +212,14 @@ class DFHACK_EXPORT StockpileIterator : public std::iterator<std::input_iterator
df::map_block* block;
size_t current;
df::item *item;
public:
StockpileIterator() {
stockpile = NULL;
block = NULL;
item = NULL;
}
StockpileIterator& operator++() {
while (stockpile) {
if (block) {
@ -230,7 +230,7 @@ public:
block = Maps::getTileBlock(stockpile->x1, stockpile->y1, stockpile->z);
current = 0;
}
while (current >= block->items.size()) {
// Out of items in this block; find the next block to search.
if (block->map_pos.x + 16 < stockpile->x2) {
@ -246,39 +246,39 @@ public:
return *this;
}
}
// If the current item isn't properly stored, move on to the next.
item = df::item::find(block->items[current]);
if (!item->flags.bits.on_ground) {
continue;
}
if (!Buildings::containsTile(stockpile, item->pos, false)) {
continue;
}
// Ignore empty bins, barrels, and wheelbarrows assigned here.
if (item->isAssignedToThisStockpile(stockpile->id)) {
auto ref = Items::getGeneralRef(item, df::general_ref_type::CONTAINS_ITEM);
if (!ref) continue;
}
// Found a valid item; yield it.
break;
}
return *this;
}
void begin(df::building_stockpilest* sp) {
stockpile = sp;
operator++();
}
df::item* operator*() {
return item;
}
bool done() {
return block == NULL;
}

@ -59,7 +59,7 @@ namespace DFHack {
}
};
struct InventoryItem {
//it has to keep the id of an item because the item itself may have been deallocated
int32_t itemId;
@ -74,7 +74,7 @@ namespace DFHack {
InventoryChangeData() {}
InventoryChangeData(int32_t id_in, InventoryItem* old_in, InventoryItem* new_in): unitId(id_in), item_old(old_in), item_new(new_in) {}
};
struct UnitAttackData {
int32_t attacker;
int32_t defender;
@ -89,7 +89,7 @@ namespace DFHack {
int32_t attackReport;
int32_t defendReport;
};
DFHACK_EXPORT void registerListener(EventType::EventType e, EventHandler handler, Plugin* plugin);
DFHACK_EXPORT int32_t registerTick(EventHandler handler, int32_t when, Plugin* plugin, bool absolute=false);
DFHACK_EXPORT void unregister(EventType::EventType e, EventHandler handler, Plugin* plugin);

@ -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 {

@ -181,7 +181,7 @@ extern DFHACK_EXPORT bool IsValid();
* Method for reading the geological surrounding of the currently loaded region.
* assign is a reference to an array of nine vectors of unsigned words that are to be filled with the data
* array is indexed by the BiomeOffset enum
*
*
* I omitted resolving the layer matgloss in this API, because it would
* introduce overhead by calling some method for each tile. You have to do it
* yourself.

@ -63,7 +63,7 @@ namespace Windows
uint8_t bright;
};
// our silly painter things and window things follow.
class df_window;
struct df_tilebuf

@ -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" {

@ -41,7 +41,7 @@ jobs_furnace={
},
--[[ [df.furnace_type.MetalsmithsForge]={
unpack(concat(furnaces,mechanism,anvil,crafts,coins,flask))
},
]]
--MetalsmithsForge,
@ -86,7 +86,7 @@ jobs_furnace={
},
}
jobs_workshop={
[df.workshop_type.Jewelers]={
{
name="cut gems",
@ -146,7 +146,7 @@ jobs_workshop={
items={{}},
job_fields={job_type=df.job_type.ConstructArmorStand}
},
{
name="construct blocks",
items={{}},
@ -226,13 +226,13 @@ jobs_workshop={
[df.workshop_type.Carpenters]={
--training weapons, wooden shields
defaults={item_type=df.item_type.WOOD,vector_id=df.job_item_vector_id.WOOD},
{
name="make barrel",
items={{}},
job_fields={job_type=df.job_type.MakeBarrel}
},
{
name="make bucket",
items={{}},
@ -550,7 +550,7 @@ function getJobs(buildingId,workshopId,customId)
c_jobs=jobs_workshop[workshopId]
elseif buildingId==df.building_type.Furnace then
c_jobs=jobs_furnace[workshopId]
if workshopId == df.furnace_type.Smelter or workshopId == df.furnace_type.MagmaSmelter then
c_jobs=utils.clone(c_jobs,true)
addSmeltJobs(c_jobs,workshopId == df.furnace_type.Smelter)
@ -563,7 +563,7 @@ function getJobs(buildingId,workshopId,customId)
else
c_jobs=utils.clone(c_jobs,true)
end
addReactionJobs(c_jobs,buildingId,workshopId,customId)
for jobId,contents in pairs(c_jobs) do
if jobId~="defaults" then

@ -27,22 +27,22 @@ local _ENV = mkmodule('dumper')
local dumplua_closure = [[
local closures = {}
local function closure(t)
local function closure(t)
closures[#closures+1] = t
t[1] = assert(loadstring(t[1]))
return t[1]
end
for _,t in pairs(closures) do
for i = 2,#t do
debug.setupvalue(t[1], i-1, t[i])
end
for i = 2,#t do
debug.setupvalue(t[1], i-1, t[i])
end
end
]]
local lua_reserved_keywords = {
'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for',
'function', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat',
'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for',
'function', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat',
'return', 'then', 'true', 'until', 'while' }
local function keys(t)
@ -63,7 +63,7 @@ local function keys(t)
end
local c_functions = {}
for _,lib in pairs{'_G', 'string', 'table', 'math',
for _,lib in pairs{'_G', 'string', 'table', 'math',
'io', 'os', 'coroutine', 'package', 'debug'} do
local t = _G[lib] or {}
lib = lib .. "."
@ -79,9 +79,9 @@ function DataDumper(value, varname, fastmode, ident, indent_step)
indent_step = indent_step or 2
local defined, dumplua = {}
-- Local variables for speed optimization
local string_format, type, string_dump, string_rep =
local string_format, type, string_dump, string_rep =
string.format, type, string.dump, string.rep
local tostring, pairs, table_concat =
local tostring, pairs, table_concat =
tostring, pairs, table.concat
local keycache, strvalcache, out, closure_cnt = {}, {}, {}, 0
setmetatable(strvalcache, {__index = function(t,value)
@ -94,8 +94,8 @@ function DataDumper(value, varname, fastmode, ident, indent_step)
number = function(value) return value end,
boolean = function(value) return tostring(value) end,
['nil'] = function(value) return 'nil' end,
['function'] = function(value)
return string_format("loadstring(%q)", string_dump(value))
['function'] = function(value)
return string_format("loadstring(%q)", string_dump(value))
end,
userdata = function() error("Cannot dump userdata") end,
thread = function() error("Cannot dump threads") end,
@ -124,7 +124,7 @@ function DataDumper(value, varname, fastmode, ident, indent_step)
for _,k in ipairs(lua_reserved_keywords) do
keycache[k] = '["'..k..'"] = '
end
if fastmode then
if fastmode then
fcts.table = function (value)
-- Table value
local numidx = 1
@ -142,9 +142,9 @@ function DataDumper(value, varname, fastmode, ident, indent_step)
out[#out] = string.sub(out[#out], 1, -2);
end
out[#out+1] = "}"
return ""
return ""
end
else
else
fcts.table = function (value, ident, path)
if test_defined(value, path) then return "nil" end
-- Table value
@ -174,7 +174,7 @@ function DataDumper(value, varname, fastmode, ident, indent_step)
if totallen > 80 then
sep = "\n" .. string_rep(' ', indent_step*(ident+1))
end
str = "{"..sep..table_concat(str, ","..sep).." "..sep:sub(1,-1-indent_step).."}"
str = "{"..sep..table_concat(str, ","..sep).." "..sep:sub(1,-1-indent_step).."}"
if meta then
sep = sep:sub(1,-3)
return "setmetatable("..sep..str..","..sep..metastr..sep:sub(1,-3)..")"

@ -129,9 +129,9 @@ function BuildingDialog:initBuiltinMode()
cb = self:callback('initCustomMode')
})
end
for i=0,df.building_type._last_item do
if (not WORKSHOP_ABSTRACT[i] or self.use_abstract)and not WORKSHOP_SPECIAL[i] then
self:addBuilding(choices, df.building_type[i], i, -1,-1,nil)

@ -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
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)
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)
--]]
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
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
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
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 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)
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
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)
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
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)
--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)
--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
--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
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
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
--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 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 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
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

@ -111,7 +111,7 @@ void DFHack::EventManager::unregisterAll(Plugin* plugin) {
for ( auto i = handlers[EventType::TICK].find(plugin); i != handlers[EventType::TICK].end(); i++ ) {
if ( (*i).first != plugin )
break;
removeFromTickQueue((*i).second);
}
for ( size_t a = 0; a < (size_t)EventType::EVENT_MAX; a++ ) {
@ -248,12 +248,12 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
return;
if (!df::global::world)
return;
nextItem = *df::global::item_next_id;
nextBuilding = *df::global::building_next_id;
nextInvasion = df::global::ui->invasions.next_id;
lastJobId = -1 + *df::global::job_next_id;
constructions.clear();
for ( auto i = df::global::world->constructions.begin(); i != df::global::world->constructions.end(); i++ ) {
df::construction* constr = *i;
@ -296,7 +296,7 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
for ( size_t a = 0; a < EventType::EVENT_MAX; a++ ) {
eventLastTick[a] = -1;//-1000000;
}
gameLoaded = true;
}
}
@ -309,7 +309,7 @@ void DFHack::EventManager::manageEvents(color_ostream& out) {
return;
CoreSuspender suspender;
int32_t tick = df::global::world->frame_counter;
for ( size_t a = 0; a < EventType::EVENT_MAX; a++ ) {
@ -323,10 +323,10 @@ void DFHack::EventManager::manageEvents(color_ostream& out) {
eventFrequency = bob.freq;
}
else eventFrequency = 1;
if ( tick >= eventLastTick[a] && tick - eventLastTick[a] < eventFrequency )
continue;
eventManager[a](out);
eventLastTick[a] = tick;
}
@ -369,12 +369,12 @@ static void manageJobInitiatedEvent(color_ostream& out) {
lastJobId = *df::global::job_next_id - 1;
return;
}
if ( lastJobId+1 == *df::global::job_next_id ) {
return; //no new jobs
}
multimap<Plugin*,EventHandler> copy(handlers[EventType::JOB_INITIATED].begin(), handlers[EventType::JOB_INITIATED].end());
for ( df::job_list_link* link = &df::global::world->job_list; link != NULL; link = link->next ) {
if ( link->item == NULL )
continue;
@ -384,7 +384,7 @@ static void manageJobInitiatedEvent(color_ostream& out) {
(*i).second.eventHandler(out, (void*)link->item);
}
}
lastJobId = *df::global::job_next_id - 1;
}
@ -402,7 +402,7 @@ static void manageJobCompletedEvent(color_ostream& out) {
return;
int32_t tick0 = eventLastTick[EventType::JOB_COMPLETED];
int32_t tick1 = df::global::world->frame_counter;
multimap<Plugin*,EventHandler> copy(handlers[EventType::JOB_COMPLETED].begin(), handlers[EventType::JOB_COMPLETED].end());
map<int32_t, df::job*> nowJobs;
for ( df::job_list_link* link = &df::global::world->job_list; link != NULL; link = link->next ) {
@ -410,14 +410,14 @@ static void manageJobCompletedEvent(color_ostream& out) {
continue;
nowJobs[link->item->id] = link->item;
}
#if 0
//testing info on job initiation/completion
//newly allocated jobs
for ( auto j = nowJobs.begin(); j != nowJobs.end(); j++ ) {
if ( prevJobs.find((*j).first) != prevJobs.end() )
continue;
df::job& job1 = *(*j).second;
out.print("new job\n"
" location : 0x%X\n"
@ -445,12 +445,12 @@ static void manageJobCompletedEvent(color_ostream& out) {
continue;
}
df::job& job1 = *(*j).second;
if ( job0.flags.bits.working == job1.flags.bits.working &&
(job0.completion_timer == job1.completion_timer || (job1.completion_timer > 0 && job0.completion_timer-1 == job1.completion_timer)) &&
getWorkerID(&job0) == getWorkerID(&job1) )
continue;
out.print("job change\n"
" location : 0x%X -> 0x%X\n"
" id : %d -> %d\n"
@ -472,12 +472,12 @@ static void manageJobCompletedEvent(color_ostream& out) {
);
}
#endif
for ( auto i = prevJobs.begin(); i != prevJobs.end(); i++ ) {
//if it happened within a tick, must have been cancelled by the user or a plugin: not completed
if ( tick1 <= tick0 )
continue;
if ( nowJobs.find((*i).first) != nowJobs.end() ) {
//could have just finished if it's a repeat job
df::job& job0 = *(*i).second;
@ -488,19 +488,19 @@ static void manageJobCompletedEvent(color_ostream& out) {
continue;
if ( job1.completion_timer != -1 )
continue;
//still false positive if cancelled at EXACTLY the right time, but experiments show this doesn't happen
for ( auto j = copy.begin(); j != copy.end(); j++ ) {
(*j).second.eventHandler(out, (void*)&job0);
}
continue;
}
//recently finished or cancelled job
df::job& job0 = *(*i).second;
if ( job0.flags.bits.repeat || job0.completion_timer != 0 )
continue;
for ( auto j = copy.begin(); j != copy.end(); j++ ) {
(*j).second.eventHandler(out, (void*)&job0);
}
@ -511,7 +511,7 @@ static void manageJobCompletedEvent(color_ostream& out) {
Job::deleteJobStruct((*i).second, true);
}
prevJobs.clear();
//create new jobs
for ( auto j = nowJobs.begin(); j != nowJobs.end(); j++ ) {
/*map<int32_t, df::job*>::iterator i = prevJobs.find((*j).first);
@ -538,7 +538,7 @@ static void manageUnitDeathEvent(color_ostream& out) {
//dead: if dead since last check, trigger events
if ( livingUnits.find(unit->id) == livingUnits.end() )
continue;
for ( auto i = copy.begin(); i != copy.end(); i++ ) {
(*i).second.eventHandler(out, (void*)unit->id);
}
@ -554,7 +554,7 @@ static void manageItemCreationEvent(color_ostream& out) {
if ( nextItem >= *df::global::item_next_id ) {
return;
}
multimap<Plugin*,EventHandler> copy(handlers[EventType::ITEM_CREATED].begin(), handlers[EventType::ITEM_CREATED].end());
size_t index = df::item::binsearch_index(df::global::world->items.all, nextItem, false);
if ( index != 0 ) index--;
@ -607,7 +607,7 @@ static void manageBuildingEvent(color_ostream& out) {
}
}
nextBuilding = *df::global::building_next_id;
//now alert people about destroyed buildings
for ( auto a = buildings.begin(); a != buildings.end(); ) {
int32_t id = *a;
@ -616,7 +616,7 @@ static void manageBuildingEvent(color_ostream& out) {
a++;
continue;
}
for ( auto b = copy.begin(); b != copy.end(); b++ ) {
EventHandler bob = (*b).second;
bob.eventHandler(out, (void*)id);
@ -629,7 +629,7 @@ static void manageConstructionEvent(color_ostream& out) {
if (!df::global::world)
return;
//unordered_set<df::construction*> constructionsNow(df::global::world->constructions.begin(), df::global::world->constructions.end());
multimap<Plugin*,EventHandler> copy(handlers[EventType::CONSTRUCTION].begin(), handlers[EventType::CONSTRUCTION].end());
for ( auto a = constructions.begin(); a != constructions.end(); ) {
df::construction& construction = (*a).second;
@ -645,7 +645,7 @@ static void manageConstructionEvent(color_ostream& out) {
}
a = constructions.erase(a);
}
//for ( auto a = constructionsNow.begin(); a != constructionsNow.end(); a++ ) {
for ( auto a = df::global::world->constructions.begin(); a != df::global::world->constructions.end(); a++ ) {
df::construction* construction = *a;
@ -680,7 +680,7 @@ static void manageSyndromeEvent(color_ostream& out) {
highestTime = startTime;
if ( startTime <= lastSyndromeTime )
continue;
SyndromeData data(unit->id, b);
for ( auto c = copy.begin(); c != copy.end(); c++ ) {
EventHandler handle = (*c).second;
@ -710,7 +710,7 @@ static void manageEquipmentEvent(color_ostream& out) {
if (!df::global::world)
return;
multimap<Plugin*,EventHandler> copy(handlers[EventType::INVENTORY_CHANGE].begin(), handlers[EventType::INVENTORY_CHANGE].end());
unordered_map<int32_t, InventoryItem> itemIdToInventoryItem;
unordered_set<int32_t> currentlyEquipped;
for ( auto a = df::global::world->units.all.begin(); a != df::global::world->units.all.end(); a++ ) {
@ -720,7 +720,7 @@ static void manageEquipmentEvent(color_ostream& out) {
/*if ( unit->flags1.bits.dead )
continue;
*/
auto oldEquipment = equipmentLog.find(unit->id);
bool hadEquipment = oldEquipment != equipmentLog.end();
vector<InventoryItem>* temp;
@ -750,13 +750,13 @@ static void manageEquipmentEvent(color_ostream& out) {
continue;
}
InventoryItem item_old = (*c).second;
df::unit_inventory_item& item0 = item_old.item;
df::unit_inventory_item& item1 = item_new.item;
if ( item0.mode == item1.mode && item0.body_part_id == item1.body_part_id && item0.wound_id == item1.wound_id )
continue;
//some sort of change in how it's equipped
InventoryChangeData data(unit->id, &item_old, &item_new);
for ( auto h = copy.begin(); h != copy.end(); h++ ) {
EventHandler handle = (*h).second;
@ -777,7 +777,7 @@ static void manageEquipmentEvent(color_ostream& out) {
}
if ( !hadEquipment )
delete temp;
//update equipment
vector<InventoryItem>& equipment = equipmentLog[unit->id];
equipment.clear();
@ -795,7 +795,7 @@ static void updateReportToRelevantUnits() {
if ( df::global::world->frame_counter <= reportToRelevantUnitsTime )
return;
reportToRelevantUnitsTime = df::global::world->frame_counter;
for ( size_t a = 0; a < df::global::world->units.all.size(); a++ ) {
df::unit* unit = df::global::world->units.all[a];
for ( int16_t b = df::enum_traits<df::unit_report_type>::first_item_value; b <= df::enum_traits<df::unit_report_type>::last_item_value; b++ ) {
@ -862,7 +862,7 @@ static void manageUnitAttackEvent(color_ostream& out) {
strikeReports.insert(report->id);
}
}
if ( strikeReports.empty() )
return;
updateReportToRelevantUnits();
@ -883,37 +883,37 @@ static void manageUnitAttackEvent(color_ostream& out) {
break;
reportStr = reportStr + report2->text;
}
std::vector<int32_t>& relevantUnits = reportToRelevantUnits[report->id];
if ( relevantUnits.size() != 2 ) {
continue;
}
df::unit* unit1 = df::unit::find(relevantUnits[0]);
df::unit* unit2 = df::unit::find(relevantUnits[1]);
df::unit_wound* wound1 = getWound(unit1,unit2);
df::unit_wound* wound2 = getWound(unit2,unit1);
if ( wound1 && !alreadyDone[unit1->id][unit2->id] ) {
UnitAttackData data;
data.attacker = unit1->id;
data.defender = unit2->id;
data.wound = wound1->id;
alreadyDone[data.attacker][data.defender] = 1;
for ( auto b = copy.begin(); b != copy.end(); b++ ) {
EventHandler handle = (*b).second;
handle.eventHandler(out, (void*)&data);
}
}
if ( wound2 && !alreadyDone[unit1->id][unit2->id] ) {
UnitAttackData data;
data.attacker = unit2->id;
data.defender = unit1->id;
data.wound = wound2->id;
alreadyDone[data.attacker][data.defender] = 1;
for ( auto b = copy.begin(); b != copy.end(); b++ ) {
EventHandler handle = (*b).second;
@ -932,7 +932,7 @@ static void manageUnitAttackEvent(color_ostream& out) {
handle.eventHandler(out, (void*)&data);
}
}
if ( unit2->flags1.bits.dead ) {
UnitAttackData data;
data.attacker = unit1->id;
@ -944,7 +944,7 @@ static void manageUnitAttackEvent(color_ostream& out) {
handle.eventHandler(out, (void*)&data);
}
}
if ( !wound1 && !wound2 ) {
//if ( unit1->flags1.bits.dead || unit2->flags1.bits.dead )
// continue;
@ -992,7 +992,7 @@ static std::string getVerb(df::unit* unit, std::string reportStr) {
static InteractionData getAttacker(color_ostream& out, df::report* attackEvent, df::unit* lastAttacker, df::report* defendEvent, vector<df::unit*>& relevantUnits) {
vector<df::unit*> attackers = relevantUnits;
vector<df::unit*> defenders = relevantUnits;
//find valid interactions: TODO
/*map<int32_t,vector<df::interaction*> > validInteractions;
for ( size_t a = 0; a < relevantUnits.size(); a++ ) {
@ -1000,7 +1000,7 @@ static InteractionData getAttacker(color_ostream& out, df::report* attackEvent,
vector<df::interaction*>& interactions = validInteractions[unit->id];
for ( size_t b = 0; b < unit->body.
}*/
//if attackEvent
// attacker must be same location
// attacker name must start attack str
@ -1019,7 +1019,7 @@ static InteractionData getAttacker(color_ostream& out, df::report* attackEvent,
a--;
continue;
}
std::string verbC = getVerb(attackers[a], attackEvent->text);
if ( verbC.length() == 0 ) {
attackers.erase(attackers.begin()+a);
@ -1029,7 +1029,7 @@ static InteractionData getAttacker(color_ostream& out, df::report* attackEvent,
attackVerb = verbC;
}
}
//if defendEvent
// defender must be same location
// defender name must start defend str
@ -1052,7 +1052,7 @@ static InteractionData getAttacker(color_ostream& out, df::report* attackEvent,
defendVerb = verbC;
}
}
//keep in mind one attacker zero defenders is perfectly valid for self-cast
if ( attackers.size() == 1 && defenders.size() == 1 && attackers[0] == defenders[0] ) {
//out.print("%s,%d\n",__FILE__,__LINE__);
@ -1070,7 +1070,7 @@ static InteractionData getAttacker(color_ostream& out, df::report* attackEvent,
defenders.erase(a);
}
}
//if trying attack-defend pair and it fails to find attacker, try defend only
InteractionData result = /*(InteractionData)*/ { std::string(), std::string(), -1, -1, -1, -1 };
if ( attackers.size() > 1 ) {
@ -1141,7 +1141,7 @@ static void manageInteractionEvent(color_ostream& out) {
}
if ( a < reports.size() )
updateReportToRelevantUnits();
df::report* lastAttackEvent = NULL;
df::unit* lastAttacker = NULL;
df::unit* lastDefender = NULL;

@ -1362,23 +1362,23 @@ int32_t Items::createItem(df::item_type item_type, int16_t item_subtype, int16_t
prod->product_dimension = 1;
break;
}
//makeItem
vector<df::item*> out_items;
vector<df::reaction_reagent*> in_reag;
vector<df::item*> in_items;
df::enums::game_type::game_type type = *df::global::gametype;
prod->produce(unit, &out_items, &in_reag, &in_items, 1, job_skill::NONE,
df::historical_entity::find(unit->civ_id),
((type == df::enums::game_type::DWARF_MAIN) || (type == df::enums::game_type::DWARF_RECLAIM)) ? df::world_site::find(df::global::ui->site_id) : NULL);
if ( out_items.size() != 1 )
return -1;
for (size_t a = 0; a < out_items.size(); a++ ) {
out_items[a]->moveToGround(unit->pos.x, unit->pos.y, unit->pos.z);
}
return out_items[0]->id;
}

@ -204,7 +204,7 @@ df::map_block *Maps::ensureTileBlock (int32_t x, int32_t y, int32_t z)
slot->temperature_1[tx][ty] = column[z2]->temperature_1[tx][ty];
slot->temperature_2[tx][ty] = column[z2]->temperature_2[tx][ty];
}
df::global::world->map.map_blocks.push_back(slot);
return slot;
}
@ -593,7 +593,7 @@ bool Maps::canStepBetween(df::coord pos1, df::coord pos2)
if ( !index_tile<uint16_t>(block1->walkable,pos1) || !index_tile<uint16_t>(block2->walkable,pos2) ) {
return false;
}
if ( block1->designation[pos1.x&0xF][pos1.y&0xF].bits.flow_size >= 4 ||
block2->designation[pos2.x&0xF][pos2.y&0xF].bits.flow_size >= 4 )
return false;
@ -640,7 +640,7 @@ bool Maps::canStepBetween(df::coord pos1, df::coord pos2)
}
if ( !foundWall )
return false; //unusable ramp
//there has to be an unforbidden hatch above the ramp
if ( index_tile<df::tile_occupancy>(block2->occupancy,pos2).bits.building != tile_building_occ::Dynamic )
return false;
@ -657,7 +657,7 @@ bool Maps::canStepBetween(df::coord pos1, df::coord pos2)
}
return false;
}
//diagonal up: has to be a ramp
if ( shape1 == tiletype_shape::RAMP /*&& shape2 == tiletype_shape::RAMP*/ ) {
df::coord up = df::coord(pos1.x,pos1.y,pos1.z+1);
@ -681,11 +681,11 @@ bool Maps::canStepBetween(df::coord pos1, df::coord pos2)
df::tiletype_shape shapeUp = ENUM_ATTR(tiletype,shape,*typeUp);
if ( shapeUp != tiletype_shape::RAMP_TOP )
return false;
df::map_block* blockUp = getTileBlock(up);
if ( !blockUp )
return false;
df::tile_building_occ occupancy = index_tile<df::tile_occupancy>(blockUp->occupancy,up).bits.building;
if ( occupancy == tile_building_occ::Obstacle || occupancy == tile_building_occ::Floored || occupancy == tile_building_occ::Impassable )
return false;

@ -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))
{

@ -25,7 +25,7 @@ DFHACK_PLUGIN("dfusion")
static int loadObjectFile(lua_State* L)
{
std::string path;
path=luaL_checkstring(L,1);
OutFile::File f(path);
@ -36,7 +36,7 @@ static int loadObjectFile(lua_State* L)
lua_setfield(L,table_pos,"data_size");
char* buf=new char[size];
f.GetText(buf);
//Lua::PushDFObject(L,DFHack::,buf);
//Lua::Push(L,buf);
lua_pushlightuserdata(L,buf);
@ -52,7 +52,7 @@ static int loadObjectFile(lua_State* L)
Lua::Push(L,symbols[i].pos);
lua_setfield(L,-2,"pos");
lua_settable(L,-3);
}
lua_setfield(L,table_pos,"symbols");

@ -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);
}

@ -5,7 +5,7 @@ File::File(std::string path)
{
//mystream.exceptions ( std::fstream::eofbit | std::fstream::failbit | std::fstream::badbit );
mystream.open(path.c_str(),std::fstream::binary|std::ios::in|std::ios::out);
if(mystream)
{

@ -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;
if(!st.is<lua::nil>(3))
buf=(uint8_t*)lua_touserdata(st,3);
else
buf=new uint8_t[len];
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];
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");
}

@ -1,4 +1,4 @@
// automatically chop trees
// automatically chop trees
#include "uicommon.h"
@ -549,7 +549,7 @@ public:
}
std::string getFocusString() { return "autochop"; }
void updateAutochopBurrows()
{
watchedBurrows.clear();
@ -586,7 +586,7 @@ struct autochop_hook : public df::viewscreen_dwarfmodest
using namespace df::enums::ui_sidebar_mode;
return (ui->main.mode == DesignateChopTrees);
}
void sendKey(const df::interface_key &key)
{
set<df::interface_key> tmp;

@ -220,7 +220,7 @@ struct dump_hook : public df::viewscreen_dwarfmodest
links += sp->links.give_to_workshop.size();
links += sp->links.take_from_workshop.size();
bool state = monitor.isMonitored(sp);
if (links + 12 >= y) {
y = dims.y2;
OutputString(COLOR_WHITE, x, y, "Auto: ");

@ -59,8 +59,8 @@ struct MaterialDescriptor
bool matches(const MaterialDescriptor &a) const
{
return a.valid && valid &&
a.type == type &&
return a.valid && valid &&
a.type == type &&
a.index == index &&
a.item_type == item_type &&
a.item_subtype == item_subtype;
@ -141,15 +141,15 @@ static bool allow_future_placement = false;
static inline bool in_material_choice_stage()
{
return Gui::build_selector_hotkey(Core::getTopViewscreen()) &&
return Gui::build_selector_hotkey(Core::getTopViewscreen()) &&
ui_build_selector->building_type == df::building_type::Construction &&
ui->main.mode == ui_sidebar_mode::Build &&
ui->main.mode == ui_sidebar_mode::Build &&
ui_build_selector->stage == 2;
}
static inline bool in_placement_stage()
{
return Gui::dwarfmode_hotkey(Core::getTopViewscreen()) &&
return Gui::dwarfmode_hotkey(Core::getTopViewscreen()) &&
ui->main.mode == ui_sidebar_mode::Build &&
ui_build_selector &&
ui_build_selector->building_type == df::building_type::Construction &&
@ -158,7 +158,7 @@ static inline bool in_placement_stage()
static inline bool in_type_choice_stage()
{
return Gui::dwarfmode_hotkey(Core::getTopViewscreen()) &&
return Gui::dwarfmode_hotkey(Core::getTopViewscreen()) &&
ui->main.mode == ui_sidebar_mode::Build &&
ui_build_selector &&
ui_build_selector->building_type < 0;
@ -269,7 +269,7 @@ static bool check_autoselect(MaterialDescriptor &material, bool toggle)
size_t idx;
if (is_material_in_autoselect(idx, material))
{
if (toggle)
if (toggle)
vector_erase_at(get_curr_constr_prefs(), idx);
return true;
@ -440,7 +440,7 @@ static bool is_valid_building_site(building_site &site, bool orthogonal_check, b
}
else if (orthogonal_check)
{
if (shape != tiletype_shape::RAMP &&
if (shape != tiletype_shape::RAMP &&
shape_basic != tiletype_shape_basic::Floor &&
shape_basic != tiletype_shape_basic::Stair)
return false;
@ -945,7 +945,7 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest
{
// First valid site is guaranteed to be anchored, either on a tile or against a valid orthogonal tile
// Use it as an anchor point to generate materials list
anchor = valid_building_sites.front();
anchor = valid_building_sites.front();
valid_building_sites.pop_front();
valid_building_sites.push_back(anchor);
}
@ -1057,8 +1057,8 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest
int16_t last_used_constr_subtype = (in_material_choice_stage()) ? ui_build_selector->building_subtype : -1;
INTERPOSE_NEXT(feed)(input);
if (revert_to_last_used_type &&
last_used_constr_subtype >= 0 &&
if (revert_to_last_used_type &&
last_used_constr_subtype >= 0 &&
in_type_choice_stage() &&
hotkeys.find(last_used_constr_subtype) != hotkeys.end())
{

@ -226,7 +226,7 @@ struct melt_hook : public df::viewscreen_dwarfmodest
int left_margin = dims.menu_x1 + 1;
int x = left_margin;
int y = dims.y2 - 6;
int links = 0;
links += sp->links.give_to_pile.size();
links += sp->links.take_from_pile.size();

@ -142,7 +142,7 @@ static bool check_mandates(df::item *item)
if (mandate->mode != 0)
continue;
if (item->getType() != mandate->item_type ||
if (item->getType() != mandate->item_type ||
(mandate->item_subtype != -1 && item->getSubtype() != mandate->item_subtype))
continue;
@ -421,14 +421,14 @@ struct trade_hook : public df::viewscreen_dwarfmodest
int left_margin = dims.menu_x1 + 1;
int x = left_margin;
int y = dims.y2 - 5;
int links = 0;
links += sp->links.give_to_pile.size();
links += sp->links.take_from_pile.size();
links += sp->links.give_to_workshop.size();
links += sp->links.take_from_workshop.size();
bool state = monitor.isMonitored(sp);
if (links + 12 >= y) {
y = dims.y2;
OutputString(COLOR_WHITE, x, y, "Auto: ");

@ -72,12 +72,12 @@ pair<uint32_t, uint32_t> get_building_size(df::building* b)
char get_tile_dig(MapExtras::MapCache mc, int32_t x, int32_t y, int32_t z)
{
df::tiletype tt = mc.tiletypeAt(DFCoord(x, y, z));
df::tiletype tt = mc.tiletypeAt(DFCoord(x, y, z));
df::tiletype_shape ts = tileShape(tt);
switch (ts)
{
case tiletype_shape::EMPTY:
case tiletype_shape::RAMP_TOP:
case tiletype_shape::RAMP_TOP:
return 'h';
case tiletype_shape::FLOOR:
case tiletype_shape::BOULDER:
@ -102,7 +102,7 @@ char get_tile_dig(MapExtras::MapCache mc, int32_t x, int32_t y, int32_t z)
string get_tile_build(uint32_t x, uint32_t y, df::building* b)
{
if (! b)
if (! b)
return " ";
bool at_nw_corner = x == b->x1 && y == b->y1;
bool at_se_corner = x == b->x2 && y == b->y2;
@ -366,7 +366,7 @@ string get_tile_build(uint32_t x, uint32_t y, df::building* b)
out << "CS";
if (ts->use_dump)
{
if (ts->dump_x_shift == 0)
if (ts->dump_x_shift == 0)
{
if (ts->dump_y_shift > 0)
out << "dd";
@ -429,7 +429,7 @@ string get_tile_build(uint32_t x, uint32_t y, df::building* b)
case building_type::AxleVertical:
return "Mv";
case building_type::Rollers:
if (! at_nw_corner)
if (! at_nw_corner)
return "`";
out << "Mr";
switch (((df::building_rollersst*) b)->direction)
@ -440,7 +440,7 @@ string get_tile_build(uint32_t x, uint32_t y, df::building* b)
out << "s";
case screw_pump_direction::FromSouth:
out << "s";
case screw_pump_direction::FromWest:
case screw_pump_direction::FromWest:
out << "s";
}
out << "(" << size.first << "x" << size.second << ")";
@ -533,7 +533,7 @@ string get_tile_place(uint32_t x, uint32_t y, df::building* b)
out << "p";
break;
case df::stockpile_group_set::mask_armor:
out << "d";
out << "d";
break;
default: //multiple stockpile type
return "`";

@ -332,7 +332,7 @@ static int addBuilding(lua_State* L)
newDefinition.connections.can_connect.push_back(-1);//TODO add this too...
newDefinition.connections.tiles.push_back(df::coord(x,y,0));
lua_pop(L,1);
}
lua_pop(L,1);

File diff suppressed because it is too large Load Diff

@ -52,8 +52,8 @@ struct MaterialDescriptor
bool matches(const MaterialDescriptor &a) const
{
return a.valid && valid &&
a.type == type &&
return a.valid && valid &&
a.type == type &&
a.index == index &&
a.item_type == item_type &&
a.item_subtype == item_subtype;
@ -190,7 +190,7 @@ private:
masks_column.filterDisplay();
}
void populateMaterials()
{
materials_column.clear();
@ -248,7 +248,7 @@ private:
materials_column.sort();
}
void addMaterialEntry(df::dfhack_material_category &selected_category,
void addMaterialEntry(df::dfhack_material_category &selected_category,
MaterialInfo &material, std::string name)
{
if (!selected_category.whole || material.matches(selected_category))
@ -350,7 +350,7 @@ private:
}
};
// START Planning
// START Planning
class PlannedBuilding
{
public:

@ -51,7 +51,7 @@ struct buildingplan_hook : public df::viewscreen_dwarfmodest
bool isInPlannedBuildingQueryMode()
{
return (ui->main.mode == df::ui_sidebar_mode::QueryBuilding ||
return (ui->main.mode == df::ui_sidebar_mode::QueryBuilding ||
ui->main.mode == df::ui_sidebar_mode::BuildingItems) &&
planner.getSelectedPlannedBuilding();
}
@ -91,7 +91,7 @@ struct buildingplan_hook : public df::viewscreen_dwarfmodest
{
if (getNoblePositionOfSelectedBuildingOwner().size() > 0)
return canReserveRoom(world->selected_building);
else
else
return false;
}
@ -119,7 +119,7 @@ struct buildingplan_hook : public df::viewscreen_dwarfmodest
{
show_help = true;
}
if (is_planmode_enabled(type))
{
if (planner.inQuickFortMode() && planner.in_dummmy_screen)
@ -184,7 +184,7 @@ struct buildingplan_hook : public df::viewscreen_dwarfmodest
{
planner.removeSelectedPlannedBuilding(); // Remove persistent data
}
}
else if (isInNobleRoomQueryMode())
{
@ -347,7 +347,7 @@ static command_result buildingplan_cmd(color_ostream &out, vector <string> & par
{
show_debugging = (toLower(parameters[1]) == "on");
out << "Debugging " << ((show_debugging) ? "enabled" : "disabled") << endl;
}
}
}
return CR_OK;

@ -92,7 +92,7 @@ command_result catsplosion (color_ostream &out, std::vector <std::string> & para
female_counts[raw->creature_id].size(); //auto initialize the females as well
}
}
// print (optional)
//if (showcreatures == 1)
{

@ -127,7 +127,7 @@ command_result df_changeitem(color_ostream &out, vector <string> & parameters)
for (size_t i = 0; i < parameters.size(); i++)
{
string & p = parameters[i];
if (p == "help" || p == "?")
{
out << changeitem_help << endl;
@ -328,7 +328,7 @@ command_result changeitem_execute(
out << " quality: " << describeQuality(item->getQuality()) << endl;
//if(item->isImproved())
// out << " imp.quality: " << describeQuality(item->getImprovementQuality()) << endl;
out << " material: " << mat_old.getToken() << endl;
out << " material: " << mat_old.getToken() << endl;
return CR_OK;
}
@ -350,7 +350,7 @@ command_result changeitem_execute(
// fixme: changing material of cloth items needs more work...
// <_Q> cloth items have a "CLOTH" improvement which tells you about the cloth that was used to make it
if(force||(mat_old.subtype == mat_new.subtype && mat_old.mode==mat_new.mode))
{
item->setMaterial(mat_new.type);

@ -32,8 +32,8 @@ DFHACK_PLUGIN("changelayer");
REQUIRE_GLOBAL(world);
REQUIRE_GLOBAL(cursor);
const string changelayer_help =
" Allows to change the material of whole geology layers.\n"
const string changelayer_help =
" Allows to change the material of whole geology layers.\n"
" Can have impact on all surrounding regions, not only your embark!\n"
" By default changing stone to soil and vice versa is not allowed.\n"
" By default changes only the layer at the cursor position.\n"
@ -47,7 +47,7 @@ const string changelayer_help =
" all_biomes - Change layer for all biomes on your map.\n"
" Result may be undesirable since the same layer\n"
" can AND WILL be on different z-levels for different biomes.\n"
" Use the tool 'probe' to get an idea how layers and biomes\n"
" Use the tool 'probe' to get an idea how layers and biomes\n"
" are distributed on your map.\n"
" all_layers - Change all layers on your map.\n"
" Candy mountain, anyone?\n"
@ -70,7 +70,7 @@ const string changelayer_help =
" changelayer MARBLE allbiomes alllayers\n"
" Convert all layers of all biomes into marble.\n";
const string changelayer_trouble =
const string changelayer_trouble =
"Known problems with changelayer:\n\n"
" Nothing happens, the material stays the old.\n"
" Pause/unpause the game and/or move the cursor a bit. Then retry.\n"
@ -108,7 +108,7 @@ static bool warned = false;
command_result changelayer (color_ostream &out, std::vector <std::string> & parameters)
{
CoreSuspender suspend;
CoreSuspender suspend;
string material;
bool force = false;
@ -209,13 +209,13 @@ command_result changelayer (color_ostream &out, std::vector <std::string> & para
// there is no Maps::WriteGeology or whatever, and I didn't want to mess with the library and add it
// so I copied the stuff which reads the geology information and modified it to be able to change it
//
//
// a more elegant solution would probably look like this:
// 1) modify Maps::ReadGeology to accept and fill one more optional vector
// 1) modify Maps::ReadGeology to accept and fill one more optional vector
// where the geolayer ids of the 9 biomes are stored
// 2) call ReadGeology here, modify the data in the vectors without having to do all that map stuff
// 3) write Maps::WriteGeology, pass the vectors, let it do it's work
// Step 1) is optional, but it would make implementing 3) easier.
// Step 1) is optional, but it would make implementing 3) easier.
// Otherwise that "check which geo_index is used by biome X" loop would need to be done again.
// no need to touch the same geology more than once
@ -226,17 +226,17 @@ command_result changelayer (color_ostream &out, std::vector <std::string> & para
// iterate over 8 surrounding regions + local region
for (int i = eNorthWest; i < eBiomeCount; i++)
{
if(verbose)
if(verbose)
out << "---Biome: " << i;
if(!all_biomes && i!=biome)
{
if(verbose)
if(verbose)
out << "-skipping" << endl;
continue;
}
else
{
if(verbose)
if(verbose)
out << "-checking" << endl;
}
@ -304,9 +304,9 @@ command_result changelayer (color_ostream &out, std::vector <std::string> & para
if(conversionAllowed(out, mat_new, mat_old, force))
{
if(verbose)
out << "changing geolayer " << j
<< " from " << mat_old.getToken()
<< " to " << mat_new.getToken()
out << "changing geolayer " << j
<< " from " << mat_old.getToken()
<< " to " << mat_new.getToken()
<< endl;
geolayers[j]->mat_index = mat_new.index;
}
@ -329,7 +329,7 @@ command_result changelayer (color_ostream &out, std::vector <std::string> & para
}
out.print("Done.\n");
// Give control back to DF.
return CR_OK;
}

@ -326,7 +326,7 @@ command_result df_createitem (color_ostream &out, vector <string> & parameters)
out.printerr("The creature you specified has no such caste!\n");
return CR_FAILURE;
}
}
}
}
if (mat_type == -1)
{

@ -127,7 +127,7 @@ void setUnitNickname(df::unit *unit, const std::string &nick)
std::string determineCurse(df::unit * unit)
{
string cursetype = "unknown";
// ghosts: ghostly, duh
// as of DF 34.05 and higher vampire ghosts and the like should not be possible
// if they get reintroduced later it will become necessary to watch 'ghostly' seperately
@ -140,17 +140,17 @@ std::string determineCurse(df::unit * unit)
cursetype = "zombie";
// necromancers: alive, don't eat, don't drink, don't age
if(!unit->curse.add_tags1.bits.NOT_LIVING
&& unit->curse.add_tags1.bits.NO_EAT
&& unit->curse.add_tags1.bits.NO_DRINK
if(!unit->curse.add_tags1.bits.NOT_LIVING
&& unit->curse.add_tags1.bits.NO_EAT
&& unit->curse.add_tags1.bits.NO_DRINK
&& unit->curse.add_tags2.bits.NO_AGING
)
cursetype = "necromancer";
// werecreatures: alive, DO eat, DO drink, don't age
if(!unit->curse.add_tags1.bits.NOT_LIVING
&& !unit->curse.add_tags1.bits.NO_EAT
&& !unit->curse.add_tags1.bits.NO_DRINK
if(!unit->curse.add_tags1.bits.NOT_LIVING
&& !unit->curse.add_tags1.bits.NO_EAT
&& !unit->curse.add_tags1.bits.NO_DRINK
&& unit->curse.add_tags2.bits.NO_AGING )
cursetype = "werebeast";
@ -199,7 +199,7 @@ command_result cursecheck (color_ostream &out, vector <string> & parameters)
if(parameters[i] == "verbose")
{
// verbose makes no sense without enabling details
giveDetails = true;
giveDetails = true;
verbose = true;
}
}
@ -234,7 +234,7 @@ command_result cursecheck (color_ostream &out, vector <string> & parameters)
cursecount++;
string cursetype = determineCurse(unit);
if(giveNick)
{
setUnitNickname(unit, cursetype); //"CURSED");
@ -266,12 +266,12 @@ command_result cursecheck (color_ostream &out, vector <string> & parameters)
{
missing = true;
}
out.print("born in %d, cursed in %d to be a %s. (%s%s%s)\n",
unit->relations.birth_year,
unit->relations.curse_year,
cursetype.c_str(),
// technically most cursed creatures are undead,
// technically most cursed creatures are undead,
// therefore output 'active' if they are not completely dead
unit->flags1.bits.dead ? "deceased" : "active",
unit->flags3.bits.ghostly ? "-ghostly" : "",
@ -298,6 +298,6 @@ command_result cursecheck (color_ostream &out, vector <string> & parameters)
out.print("Number of cursed creatures on map: %d \n", cursecount);
else
out.print("Number of cursed creatures on tile: %d \n", cursecount);
return CR_OK;
}

File diff suppressed because it is too large Load Diff

@ -91,7 +91,7 @@ command_result writeFlag (color_ostream &out, vector <string> & parameters)
case '7':
value = parameters[0][0] - '0';
break;
default:
out.print("Invalid value specified\n");
return CR_FAILURE;

@ -70,7 +70,7 @@ command_result eventExample(color_ostream& out, vector<string>& parameters) {
}
}
*/
EventManager::EventHandler initiateHandler(jobInitiated, 1);
EventManager::EventHandler completeHandler(jobCompleted, 0);
EventManager::EventHandler timeHandler(timePassed, 1);
@ -82,7 +82,7 @@ command_result eventExample(color_ostream& out, vector<string>& parameters) {
EventManager::EventHandler invasionHandler(invasion, 1000);
EventManager::EventHandler unitAttackHandler(unitAttack, 1);
EventManager::unregisterAll(plugin_self);
EventManager::registerListener(EventManager::EventType::JOB_INITIATED, initiateHandler, plugin_self);
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, completeHandler, plugin_self);
EventManager::registerListener(EventManager::EventType::UNIT_DEATH, deathHandler, plugin_self);
@ -105,7 +105,7 @@ command_result eventExample(color_ostream& out, vector<string>& parameters) {
timeHandler.freq = t;
EventManager::unregister(EventManager::EventType::TICK, timeHandler, plugin_self);
EventManager::unregister(EventManager::EventType::TICK, timeHandler, plugin_self);
out.print("Events registered.\n");
return CR_OK;
}
@ -159,7 +159,7 @@ void construction(color_ostream& out, void* ptr) {
out.print(" construction destroyed\n");
else
out.print(" construction created\n");
}
void syndrome(color_ostream& out, void* ptr) {

@ -65,12 +65,12 @@ public:
t_itemflags &f = itm->origin->flags;
return (f.unk1 || f.unk2 || f.unk3 || f.unk4 ||
return (f.unk1 || f.unk2 || f.unk3 || f.unk4 ||
f.unk6 || f.unk7 ||
f.unk10 || f.unk11);
}
virtual void postPrint(DFHack::dfh_item *itm)
virtual void postPrint(DFHack::dfh_item *itm)
{
std::vector<std::string> flags;

@ -1,189 +1,189 @@
#include "Core.h"
#include "Console.h"
#include "PluginManager.h"
#include "MemAccess.h"
#include "MiscUtils.h"
#include <tinythread.h> //not sure if correct
#include <string>
#include <vector>
#include <sstream>
using std::vector;
using std::string;
using namespace DFHack;
uint64_t timeLast=0;
static tthread::mutex* mymutex=0;
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
struct memory_data
{
void * addr;
size_t len;
size_t refresh;
int state;
uint8_t *buf,*lbuf;
vector<t_memrange> ranges;
}memdata;
enum HEXVIEW_STATES
{
STATE_OFF,STATE_ON
};
command_result memview (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("memview");
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.push_back(PluginCommand("memview","Shows memory in real time. Params: adrr length refresh_rate. If addr==0 then stop viewing",memview));
memdata.state=STATE_OFF;
mymutex=new tthread::mutex;
return CR_OK;
}
size_t convert(const std::string& p,bool ishex=false)
{
size_t ret;
std::stringstream conv;
if(ishex)
conv<<std::hex;
conv<<p;
conv>>ret;
return ret;
}
bool isAddr(uint32_t *trg,vector<t_memrange> & ranges)
{
if(trg[0]%4==0)
for(size_t i=0;i<ranges.size();i++)
if(ranges[i].isInRange((void *)trg[0]))
return true;
return false;
}
void outputHex(uint8_t *buf,uint8_t *lbuf,size_t len,size_t start,color_ostream &con,vector<t_memrange> & ranges)
{
const size_t page_size=16;
for(size_t i=0;i<len;i+=page_size)
{
//con.gotoxy(1,i/page_size+1);
con.print("0x%08X ",i+start);
for(size_t j=0;(j<page_size) && (i+j<len);j++)
{
if(j%4==0)
{
con.reset_color();
if(isAddr((uint32_t *)(buf+j+i),ranges))
con.color(COLOR_LIGHTRED); //coloring in the middle does not work
//TODO make something better?
}
if(lbuf[j+i]!=buf[j+i])
con.print("*%02X",buf[j+i]); //if modfied show a star
else
con.print(" %02X",buf[j+i]);
}
con.reset_color();
con.print(" | ");
for(size_t j=0;(j<page_size) && (i+j<len);j++)
if((buf[j+i]>31)&&(buf[j+i]<128)) //only printable ascii
con.print("%c",buf[j+i]);
else
con.print(".");
//con.print("\n");
}
con.print("\n");
}
void Deinit()
{
if(memdata.state==STATE_ON)
{
is_enabled = false;
memdata.state=STATE_OFF;
delete [] memdata.buf;
delete [] memdata.lbuf;
}
}
DFhackCExport command_result plugin_onupdate (color_ostream &out)
{
mymutex->lock();
if(memdata.state==STATE_OFF)
{
mymutex->unlock();
return CR_OK;
}
//Console &con=out;
uint64_t time2 = GetTimeMs64();
uint64_t delta = time2-timeLast;
if(memdata.refresh!=0)
if(delta<memdata.refresh)
{
mymutex->unlock();
return CR_OK;
}
timeLast = time2;
Core::getInstance().p->read(memdata.addr,memdata.len,memdata.buf);
outputHex(memdata.buf,memdata.lbuf,memdata.len,(size_t)memdata.addr,out,memdata.ranges);
memcpy(memdata.lbuf, memdata.buf, memdata.len);
if(memdata.refresh==0)
Deinit();
mymutex->unlock();
return CR_OK;
}
command_result memview (color_ostream &out, vector <string> & parameters)
{
mymutex->lock();
Core::getInstance().p->getMemRanges(memdata.ranges);
memdata.addr=(void *)convert(parameters[0],true);
if(memdata.addr==0)
{
Deinit();
memdata.state=STATE_OFF;
is_enabled = false;
mymutex->unlock();
return CR_OK;
}
else
{
Deinit();
bool isValid=false;
for(size_t i=0;i<memdata.ranges.size();i++)
if(memdata.ranges[i].isInRange(memdata.addr))
isValid=true;
if(!isValid)
{
out.printerr("Invalid address:%x\n",memdata.addr);
mymutex->unlock();
return CR_OK;
}
is_enabled = true;
memdata.state=STATE_ON;
}
if(parameters.size()>1)
memdata.len=convert(parameters[1]);
else
memdata.len=20*16;
if(parameters.size()>2)
memdata.refresh=convert(parameters[2]);
else
memdata.refresh=0;
memdata.buf=new uint8_t[memdata.len];
memdata.lbuf=new uint8_t[memdata.len];
Core::getInstance().p->getMemRanges(memdata.ranges);
mymutex->unlock();
return CR_OK;
}
DFhackCExport command_result plugin_shutdown (color_ostream &out)
{
mymutex->lock();
Deinit();
delete mymutex;
mymutex->unlock();
return CR_OK;
}
#include "Core.h"
#include "Console.h"
#include "PluginManager.h"
#include "MemAccess.h"
#include "MiscUtils.h"
#include <tinythread.h> //not sure if correct
#include <string>
#include <vector>
#include <sstream>
using std::vector;
using std::string;
using namespace DFHack;
uint64_t timeLast=0;
static tthread::mutex* mymutex=0;
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
struct memory_data
{
void * addr;
size_t len;
size_t refresh;
int state;
uint8_t *buf,*lbuf;
vector<t_memrange> ranges;
}memdata;
enum HEXVIEW_STATES
{
STATE_OFF,STATE_ON
};
command_result memview (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("memview");
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.push_back(PluginCommand("memview","Shows memory in real time. Params: adrr length refresh_rate. If addr==0 then stop viewing",memview));
memdata.state=STATE_OFF;
mymutex=new tthread::mutex;
return CR_OK;
}
size_t convert(const std::string& p,bool ishex=false)
{
size_t ret;
std::stringstream conv;
if(ishex)
conv<<std::hex;
conv<<p;
conv>>ret;
return ret;
}
bool isAddr(uint32_t *trg,vector<t_memrange> & ranges)
{
if(trg[0]%4==0)
for(size_t i=0;i<ranges.size();i++)
if(ranges[i].isInRange((void *)trg[0]))
return true;
return false;
}
void outputHex(uint8_t *buf,uint8_t *lbuf,size_t len,size_t start,color_ostream &con,vector<t_memrange> & ranges)
{
const size_t page_size=16;
for(size_t i=0;i<len;i+=page_size)
{
//con.gotoxy(1,i/page_size+1);
con.print("0x%08X ",i+start);
for(size_t j=0;(j<page_size) && (i+j<len);j++)
{
if(j%4==0)
{
con.reset_color();
if(isAddr((uint32_t *)(buf+j+i),ranges))
con.color(COLOR_LIGHTRED); //coloring in the middle does not work
//TODO make something better?
}
if(lbuf[j+i]!=buf[j+i])
con.print("*%02X",buf[j+i]); //if modfied show a star
else
con.print(" %02X",buf[j+i]);
}
con.reset_color();
con.print(" | ");
for(size_t j=0;(j<page_size) && (i+j<len);j++)
if((buf[j+i]>31)&&(buf[j+i]<128)) //only printable ascii
con.print("%c",buf[j+i]);
else
con.print(".");
//con.print("\n");
}
con.print("\n");
}
void Deinit()
{
if(memdata.state==STATE_ON)
{
is_enabled = false;
memdata.state=STATE_OFF;
delete [] memdata.buf;
delete [] memdata.lbuf;
}
}
DFhackCExport command_result plugin_onupdate (color_ostream &out)
{
mymutex->lock();
if(memdata.state==STATE_OFF)
{
mymutex->unlock();
return CR_OK;
}
//Console &con=out;
uint64_t time2 = GetTimeMs64();
uint64_t delta = time2-timeLast;
if(memdata.refresh!=0)
if(delta<memdata.refresh)
{
mymutex->unlock();
return CR_OK;
}
timeLast = time2;
Core::getInstance().p->read(memdata.addr,memdata.len,memdata.buf);
outputHex(memdata.buf,memdata.lbuf,memdata.len,(size_t)memdata.addr,out,memdata.ranges);
memcpy(memdata.lbuf, memdata.buf, memdata.len);
if(memdata.refresh==0)
Deinit();
mymutex->unlock();
return CR_OK;
}
command_result memview (color_ostream &out, vector <string> & parameters)
{
mymutex->lock();
Core::getInstance().p->getMemRanges(memdata.ranges);
memdata.addr=(void *)convert(parameters[0],true);
if(memdata.addr==0)
{
Deinit();
memdata.state=STATE_OFF;
is_enabled = false;
mymutex->unlock();
return CR_OK;
}
else
{
Deinit();
bool isValid=false;
for(size_t i=0;i<memdata.ranges.size();i++)
if(memdata.ranges[i].isInRange(memdata.addr))
isValid=true;
if(!isValid)
{
out.printerr("Invalid address:%x\n",memdata.addr);
mymutex->unlock();
return CR_OK;
}
is_enabled = true;
memdata.state=STATE_ON;
}
if(parameters.size()>1)
memdata.len=convert(parameters[1]);
else
memdata.len=20*16;
if(parameters.size()>2)
memdata.refresh=convert(parameters[2]);
else
memdata.refresh=0;
memdata.buf=new uint8_t[memdata.len];
memdata.lbuf=new uint8_t[memdata.len];
Core::getInstance().p->getMemRanges(memdata.ranges);
mymutex->unlock();
return CR_OK;
}
DFhackCExport command_result plugin_shutdown (color_ostream &out)
{
mymutex->lock();
Deinit();
delete mymutex;
mymutex->unlock();
return CR_OK;
}

@ -527,7 +527,7 @@ command_result df_tiles (Core * c, vector <string> & parameters)
}
else
{
cout << "flow bit 1 = " << bflags.bits.liquid_1 << endl;
cout << "flow bit 1 = " << bflags.bits.liquid_1 << endl;
cout << "flow bit 2 = " << bflags.bits.liquid_2 << endl;
}
biter ++;

@ -156,7 +156,7 @@ command_result df_vectors (color_ostream &con, vector <string> & parameters)
vectorsUsage(con);
return CR_FAILURE;
}
if (!hexOrDec(parameters[1], bytes))
{
vectorsUsage(con);
@ -273,7 +273,7 @@ command_result df_clearvec (color_ostream &con, vector <string> & parameters)
vectorsUsage(con);
return CR_FAILURE;
}
if (!hexOrDec(parameters[1], bytes))
{
vectorsUsage(con);

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

@ -1156,7 +1156,7 @@ command_result diglx (color_ostream &out, vector <string> & parameters)
return digl(out,lol);
}
// TODO:
// TODO:
// digl and digv share the longish floodfill code and only use different conditions
// to check if a tile should be marked for digging or not.
// to make the plugin a bit smaller and cleaner a main execute method would be nice
@ -1377,7 +1377,7 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
out.printerr("Too many parameters.\n");
return CR_FAILURE;
}
uint32_t targetDigType;
if ( parameters.size() == 1 )
{
@ -1406,13 +1406,13 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
{
targetDigType = -1;
}
if (!Maps::IsValid())
{
out.printerr("Map is not available!\n");
return CR_FAILURE;
}
int32_t cx, cy, cz;
uint32_t xMax,yMax,zMax;
Maps::getSize(xMax,yMax,zMax);
@ -1436,7 +1436,7 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
return CR_FAILURE;
}
out.print("(%d,%d,%d) tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, baseDes.whole);
if ( targetDigType != -1 )
{
baseDes.bits.dig = (tile_dig_designation::tile_dig_designation)targetDigType;
@ -1448,7 +1448,7 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
baseDes.bits.dig = tile_dig_designation::Default;
}
}
for( uint32_t z = 0; z < zMax; z++ )
{
for( uint32_t x = 1; x < tileXMax-1; x++ )
@ -1462,7 +1462,7 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
tt = mCache->tiletypeAt(current);
if (!DFHack::isWallTerrain(tt))
continue;
//designate it for digging
df::tile_designation des = mCache->designationAt(current);
if ( !mCache->testCoord(current) )
@ -1471,14 +1471,14 @@ command_result digtype (color_ostream &out, vector <string> & parameters)
delete mCache;
return CR_FAILURE;
}
df::tile_designation designation = mCache->designationAt(current);
designation.bits.dig = baseDes.bits.dig;
mCache->setDesignationAt(current, designation);
}
}
}
mCache->WriteAll();
delete mCache;
return CR_OK;

@ -38,7 +38,7 @@ set<string> autodigMaterials;
DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) {
if (enabled == enable)
return CR_OK;
enabled = enable;
if ( enabled ) {
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, digHandler, plugin_self);
@ -79,31 +79,31 @@ void onDig(color_ostream& out, void* ptr) {
df::job* job = (df::job*)ptr;
if ( job->completion_timer > 0 )
return;
if ( job->job_type != df::enums::job_type::Dig &&
job->job_type != df::enums::job_type::CarveUpwardStaircase &&
job->job_type != df::enums::job_type::CarveDownwardStaircase &&
job->job_type != df::enums::job_type::CarveUpDownStaircase &&
job->job_type != df::enums::job_type::CarveRamp &&
job->job_type != df::enums::job_type::CarveUpwardStaircase &&
job->job_type != df::enums::job_type::CarveDownwardStaircase &&
job->job_type != df::enums::job_type::CarveUpDownStaircase &&
job->job_type != df::enums::job_type::CarveRamp &&
job->job_type != df::enums::job_type::DigChannel )
return;
set<df::coord> jobLocations;
for ( df::job_list_link* link = &world->job_list; link != NULL; link = link->next ) {
if ( link->item == NULL )
continue;
if ( link->item->job_type != df::enums::job_type::Dig &&
link->item->job_type != df::enums::job_type::CarveUpwardStaircase &&
link->item->job_type != df::enums::job_type::CarveDownwardStaircase &&
link->item->job_type != df::enums::job_type::CarveUpDownStaircase &&
link->item->job_type != df::enums::job_type::CarveRamp &&
link->item->job_type != df::enums::job_type::CarveUpwardStaircase &&
link->item->job_type != df::enums::job_type::CarveDownwardStaircase &&
link->item->job_type != df::enums::job_type::CarveUpDownStaircase &&
link->item->job_type != df::enums::job_type::CarveRamp &&
link->item->job_type != df::enums::job_type::DigChannel )
continue;
jobLocations.insert(link->item->pos);
}
MapExtras::MapCache cache;
df::coord pos = job->pos;
for ( int16_t a = -1; a <= 1; a++ ) {
@ -118,23 +118,23 @@ void maybeExplore(color_ostream& out, MapExtras::MapCache& cache, df::coord pt,
if ( !Maps::isValidTilePos(pt) ) {
return;
}
df::map_block* block = Maps::getTileBlock(pt);
if (!block)
return;
if ( block->designation[pt.x&0xF][pt.y&0xF].bits.hidden )
return;
df::tiletype type = block->tiletype[pt.x&0xF][pt.y&0xF];
if ( ENUM_ATTR(tiletype, material, type) != df::enums::tiletype_material::MINERAL )
return;
if ( ENUM_ATTR(tiletype, shape, type) != df::enums::tiletype_shape::WALL )
return;
if ( block->designation[pt.x&0xF][pt.y&0xF].bits.dig != df::enums::tile_dig_designation::No )
return;
uint32_t xMax,yMax,zMax;
Maps::getSize(xMax,yMax,zMax);
if ( pt.x == 0 || pt.y == 0 || pt.x+1 == xMax*16 || pt.y+1 == yMax*16 )
@ -142,7 +142,7 @@ void maybeExplore(color_ostream& out, MapExtras::MapCache& cache, df::coord pt,
if ( jobLocations.find(pt) != jobLocations.end() ) {
return;
}
int16_t mat = cache.veinMaterialAt(pt);
if ( mat == -1 )
return;
@ -152,7 +152,7 @@ void maybeExplore(color_ostream& out, MapExtras::MapCache& cache, df::coord pt,
return;
}
}
block->designation[pt.x&0xF][pt.y&0xF].bits.dig = df::enums::tile_dig_designation::Default;
block->flags.bits.designated = true;
// *process_dig = true;
@ -174,12 +174,12 @@ command_result digFlood (color_ostream &out, std::vector <std::string> & paramet
adding = true;
continue;
}
if ( parameters[a] == "CLEAR" ) {
autodigMaterials.clear();
continue;
}
if ( parameters[a] == "digAll0" ) {
digAll = false;
continue;
@ -188,7 +188,7 @@ command_result digFlood (color_ostream &out, std::vector <std::string> & paramet
digAll = true;
continue;
}
for ( size_t b = 0; b < world->raws.inorganics.size(); b++ ) {
df::inorganic_raw* inorganic = world->raws.inorganics[b];
if ( parameters[a] == inorganic->id ) {
@ -199,16 +199,16 @@ command_result digFlood (color_ostream &out, std::vector <std::string> & paramet
goto loop;
}
}
out.print("Could not find material \"%s\".\n", parameters[a].c_str());
return CR_WRONG_USAGE;
loop: continue;
}
autodigMaterials.insert(toAdd.begin(), toAdd.end());
for ( auto a = toRemove.begin(); a != toRemove.end(); a++ )
autodigMaterials.erase(*a);
return CR_OK;
}

@ -53,7 +53,7 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
if ( !firstInvader ) {
return -1;
}
//do whatever you need to do at the first important edge
df::coord pt1 = firstImportantEdge.p1;
df::coord pt2 = firstImportantEdge.p2;
@ -63,14 +63,14 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
pt2 = temp;
}
//out.print("first important edge: (%d,%d,%d) -> (%d,%d,%d)\n", pt1.x,pt1.y,pt1.z, pt2.x,pt2.y,pt2.z);
int32_t jobId = -1;
df::map_block* block1 = Maps::getTileBlock(pt1);
df::map_block* block2 = Maps::getTileBlock(pt2);
bool passable1 = block1->walkable[pt1.x&0xF][pt1.y&0xF];
bool passable2 = block2->walkable[pt2.x&0xF][pt2.y&0xF];
df::coord location;
df::building* building = Buildings::findAtTile(pt2);
df::coord buildingPos = pt2;
@ -202,7 +202,7 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
Job::linkIntoWorld(job);
jobId = job->id;
job->completion_timer = abilities.jobDelay[CostDimension::Dig];
//TODO: test if he already has a pick
bool hasPick = false;
for ( size_t a = 0; a < firstInvader->inventory.size(); a++ ) {
@ -219,10 +219,10 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
hasPick = true;
break;
}
if ( hasPick )
return firstInvader->id;
//create and give a pick
//based on createitem.cpp
df::reaction_product_itemst *prod = NULL;
@ -240,7 +240,7 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
out.print("%s, %d: no valid item.\n", __FILE__, __LINE__);
return -1;
}
DFHack::MaterialInfo material;
if ( !material.find("OBSIDIAN") ) {
out.print("%s, %d: no water.\n", __FILE__, __LINE__);
@ -251,20 +251,20 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
prod->probability = 100;
prod->count = 1;
prod->product_dimension = 1;
vector<df::item*> out_items;
vector<df::reaction_reagent*> in_reag;
vector<df::item*> in_items;
prod->produce(firstInvader, &out_items, &in_reag, &in_items, 1, df::job_skill::NONE,
df::historical_entity::find(firstInvader->civ_id),
df::world_site::find(df::global::ui->site_id));
if ( out_items.size() != 1 ) {
out.print("%s, %d: wrong size: %d.\n", __FILE__, __LINE__, out_items.size());
return -1;
}
out_items[0]->moveToGround(firstInvader->pos.x, firstInvader->pos.y, firstInvader->pos.z);
#if 0
//check for existing item there
for ( size_t a = 0; a < firstInvader->inventory.size(); a++ ) {
@ -276,7 +276,7 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
}
#endif
Items::moveToInventory(cache, out_items[0], firstInvader, df::unit_inventory_item::T_mode::Weapon, firstInvader->body.weapon_bp);
delete prod;
}
}

@ -141,7 +141,7 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
" diggingInvaders edgesPerTick n\n makes the pathfinding algorithm work on at most n edges per tick. Set to 0 or lower to make it unlimited."
// " diggingInvaders\n Makes invaders try to dig now.\n"
));
//*df::global::debug_showambush = true;
return CR_OK;
}
@ -154,7 +154,7 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out )
DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) {
if ( enabled == enable )
return CR_OK;
enabled = enable;
EventManager::unregisterAll(plugin_self);
clearDijkstra();
@ -166,7 +166,7 @@ DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) {
EventManager::registerListener(EventManager::EventType::INVASION, handler, plugin_self);
findAndAssignInvasionJob(out, (void*)0);
}
return CR_OK;
}
@ -196,9 +196,9 @@ class PointComp {
public:
unordered_map<df::coord, cost_t, PointHash> *pointCost;
PointComp(unordered_map<df::coord, cost_t, PointHash> *p): pointCost(p) {
}
int32_t operator()(df::coord p1, df::coord p2) {
if ( p1 == p2 ) return 0;
auto i1 = pointCost->find(p1);
@ -246,11 +246,11 @@ command_result diggingInvadersCommand(color_ostream& out, std::vector<std::strin
digAbilities.erase(race);
}
a++;
} else if ( parameters[a] == "setCost" || parameters[a] == "setDelay" ) {
if ( a+3 >= parameters.size() )
return CR_WRONG_USAGE;
string raceString = parameters[a+1];
if ( digAbilities.find(raceString) == digAbilities.end() ) {
DigAbilities bob;
@ -258,7 +258,7 @@ command_result diggingInvadersCommand(color_ostream& out, std::vector<std::strin
digAbilities[raceString] = bob;
}
DigAbilities& abilities = digAbilities[raceString];
string costStr = parameters[a+2];
int32_t costDim = -1;
if ( costStr == "walk" ) {
@ -276,7 +276,7 @@ command_result diggingInvadersCommand(color_ostream& out, std::vector<std::strin
} else {
return CR_WRONG_USAGE;
}
cost_t value;
stringstream asdf(parameters[a+3]);
asdf >> value;
@ -291,15 +291,15 @@ command_result diggingInvadersCommand(color_ostream& out, std::vector<std::strin
} else if ( parameters[a] == "edgeCost" ) {
if ( a+1 >= parameters.size() )
return CR_WRONG_USAGE;
string raceString = parameters[a+1];
if ( digAbilities.find(raceString) == digAbilities.end() ) {
out.print("Race %s does not have dig abilities assigned.\n", raceString.c_str());
return CR_WRONG_USAGE;
}
DigAbilities& abilities = digAbilities[raceString];
df::coord bob = Gui::getCursorPos();
out.print("(%d,%d,%d), (%d,%d,%d): cost = %lld\n", lastDebugEdgeCostPoint.x, lastDebugEdgeCostPoint.y, lastDebugEdgeCostPoint.z, bob.x, bob.y, bob.z, getEdgeCost(out, lastDebugEdgeCostPoint, bob, abilities));
lastDebugEdgeCostPoint = bob;
@ -325,7 +325,7 @@ command_result diggingInvadersCommand(color_ostream& out, std::vector<std::strin
}
activeDigging = enabled;
out.print("diggingInvaders: enabled = %d, activeDigging = %d, edgesPerTick = %d\n", enabled, activeDigging, edgesPerTick);
return CR_OK;
}
@ -366,14 +366,14 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
CoreSuspender suspend;
//returns the worker id of the job created //used to
//out.print("%s, %d: %d\n", __FILE__, __LINE__, (int32_t)tickTime);
if ( !enabled || !activeDigging ) {
clearDijkstra();
return;
}
EventManager::unregister(EventManager::EventType::TICK, findJobTickHandler, plugin_self);
EventManager::registerTick(findJobTickHandler, 1, plugin_self);
if ( fringe.empty() ) {
df::unit* lastDigger = df::unit::find(lastInvasionDigger);
if ( lastDigger && lastDigger->job.current_job && lastDigger->job.current_job->id == lastInvasionJob ) {
@ -381,7 +381,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
}
//out.print("%s,%d: lastDigger = %d, last job = %d, last digger's job = %d\n", __FILE__, __LINE__, lastInvasionDigger, lastInvasionJob, !lastDigger ? -1 : (!lastDigger->job.current_job ? -1 : lastDigger->job.current_job->id));
lastInvasionDigger = lastInvasionJob = -1;
clearDijkstra();
unordered_set<uint16_t> invaderConnectivity;
unordered_set<uint16_t> localConnectivity;
@ -446,13 +446,13 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
return;
}
}
df::unit* firstInvader = df::unit::find(invaders[0]);
if ( firstInvader == NULL ) {
fringe.clear();
return;
}
df::creature_raw* creature_raw = df::creature_raw::find(firstInvader->race);
if ( creature_raw == NULL || digAbilities.find(creature_raw->creature_id) == digAbilities.end() ) {
//inappropriate digger: no dig abilities
@ -464,13 +464,13 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
//out << firstInvader->id << endl;
//out << firstInvader->pos.x << ", " << firstInvader->pos.y << ", " << firstInvader->pos.z << endl;
//out << __LINE__ << endl;
uint32_t xMax, yMax, zMax;
Maps::getSize(xMax,yMax,zMax);
xMax *= 16;
yMax *= 16;
MapExtras::MapCache cache;
clock_t t0 = clock();
clock_t totalEdgeTime = 0;
int32_t edgesExpanded = 0;
@ -486,7 +486,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
break;
}
closedSet.insert(pt);
if ( localPts.find(pt) != localPts.end() ) {
localPtsFound++;
if ( true || localPtsFound >= localPts.size() ) {
@ -537,7 +537,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
unordered_set<df::coord, PointHash> requiresZNeg;
unordered_set<df::coord, PointHash> requiresZPos;
//find important edges
Edge firstImportantEdge(df::coord(), df::coord(), -1);
//df::coord closest;
@ -551,7 +551,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
continue;
//closest = pt;
//closestCostEstimate = costMap[closest];
//if ( workNeeded[pt] == 0 )
//if ( workNeeded[pt] == 0 )
// continue;
while ( parentMap.find(pt) != parentMap.end() ) {
//out.print("(%d,%d,%d)\n", pt.x, pt.y, pt.z);
@ -563,7 +563,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
}
//closestCostActual += cost;
if ( Maps::canStepBetween(parent, pt) ) {
} else {
if ( pt.x == parent.x && pt.y == parent.y ) {
if ( pt.z < parent.z ) {
@ -586,14 +586,14 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
}
if ( firstImportantEdge.p1 == df::coord() )
return;
/*
if ( closestCostActual != closestCostEstimate ) {
out.print("%s,%d: closest = (%d,%d,%d), estimate = %lld != actual = %lld\n", __FILE__, __LINE__, closest.x,closest.y,closest.z, closestCostEstimate, closestCostActual);
return;
}
*/
assignJob(out, firstImportantEdge, parentMap, costMap, invaders, requiresZNeg, requiresZPos, cache, abilities);
lastInvasionDigger = firstInvader->id;
lastInvasionJob = firstInvader->job.current_job ? firstInvader->job.current_job->id : -1;
@ -605,7 +605,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
if ( invaderJobs.find(job->id) == invaderJobs.end() ) {
continue;
}
//cancel it
job->flags.bits.item_lost = 1;
out.print("%s,%d: cancelling job %d.\n", __FILE__,__LINE__, job->id);

@ -57,34 +57,34 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
cost_t cost = abilities.costWeight[CostDimension::Walk];
if ( cost < 0 )
return -1;
if ( Maps::getTileBlock(pt1) == NULL || Maps::getTileBlock(pt2) == NULL )
return -1;
df::tiletype* type2 = Maps::getTileType(pt2);
df::tiletype_shape shape2 = ENUM_ATTR(tiletype, shape, *type2);
if ( Maps::getTileBlock(pt1)->designation[pt1.x&0xF][pt1.y&0xF].bits.flow_size >= 4 )
return -1;
if ( Maps::getTileBlock(pt2)->designation[pt2.x&0xF][pt2.y&0xF].bits.flow_size >= 4 )
return -1;
if ( shape2 == df::enums::tiletype_shape::EMPTY ) {
return -1;
}
if ( shape2 == df::enums::tiletype_shape::BRANCH ||
shape2 == df::enums::tiletype_shape::TRUNK_BRANCH ||
shape2 == df::enums::tiletype_shape::TWIG )
return -1;
/*
if () {
df::map_block* temp = Maps::getTileBlock(df::coord(pt1.x,pt1.y,pt1.z-1));
if ( temp && temp->designation[pt1.x&0xF][pt1.y&0xF]
}
*/
if ( Maps::canStepBetween(pt1, pt2) ) {
return cost;
}
@ -93,11 +93,11 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
if ( building2 ) {
if ( abilities.costWeight[CostDimension::DestroyBuilding] < 0 )
return -1;
cost += abilities.costWeight[CostDimension::DestroyBuilding];
cost += abilities.costWeight[CostDimension::DestroyBuilding];
if ( dx*dx + dy*dy > 1 )
return -1;
}
bool construction2 = ENUM_ATTR(tiletype, material, *type2) == df::enums::tiletype_material::CONSTRUCTION;
if ( construction2 ) {
//smooth or not?
@ -113,7 +113,7 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
cost += abilities.costWeight[CostDimension::DestroyRoughConstruction];
}
}
if ( dz == 0 ) {
if ( !building2 && !construction2 ) {
//it has to be a wall
@ -143,7 +143,7 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
}
cost += abilities.costWeight[CostDimension::Dig];
}
bool walkable_high1 = shape1 == df::tiletype_shape::STAIR_UP || shape1 == df::tiletype_shape::STAIR_UPDOWN;
if ( !walkable_high1 ) {
if ( shape1 != df::enums::tiletype_shape::WALL ) {
@ -154,7 +154,7 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
}
cost += abilities.costWeight[CostDimension::Dig];
}
if ( building2 ) {
//moving up through an open bridge or a usable hatch is fine. other buildings are not
bool unforbiddenHatch = false;
@ -188,7 +188,7 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
if ( !unforbiddenHatch && !inactiveBridge )
return -1;
}
/*bool forbidden = false;
if ( building2 && building2->getType() == df::building_type::Hatch ) {
df::building_hatchst* hatch = (df::building_hatchst*)building2;
@ -202,7 +202,7 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
if ( !walkable_high2 ) {
if ( building2 || construction2 )
return -1;
if ( shape2 != df::enums::tiletype_shape::WALL )
return -1;
if ( abilities.costWeight[CostDimension::Dig] < 0 ) {
@ -240,14 +240,14 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
if ( bridge->direction == df::building_bridgest::T_direction::Down && pt1.y == bridge->y2 )
return -1;
}
bool forbidden = false;
if ( building1 && building1->getType() == df::building_type::Hatch ) {
df::building_hatchst* hatch = (df::building_hatchst*)building1;
if ( hatch->door_flags.bits.forbidden || hatch->door_flags.bits.closed && hatch->door_flags.bits.operated_by_mechanisms )
forbidden = true;
}
//you can deconstruct a hatch from the side
if ( building1 && forbidden /*&& building1->getType() == df::building_type::Hatch*/ ) {
/*
@ -300,7 +300,7 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
if ( minCost == -1 )
return -1;
cost += minCost;
*/
//note: assignJob is not ready for this level of sophistication, so don't allow it
return -1;
@ -312,7 +312,7 @@ cost_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2, DigAbilitie
return -1;
}
}
return cost;
}
@ -329,7 +329,7 @@ cost_t getEdgeCostOld(color_ostream& out, df::coord pt1, df::coord pt2) {
return cost;
return 100 + cost;
}
Maps::ensureTileBlock(pt1);
Maps::ensureTileBlock(pt2);
df::tiletype* type1 = Maps::getTileType(pt1);
@ -404,7 +404,7 @@ cost_t getEdgeCostOld(color_ostream& out, df::coord pt1, df::coord pt2) {
if ( shape2 == df::enums::tiletype_shape::RAMP_TOP ) {
return -1;
}
//it has to be a wall
if ( shape2 != df::enums::tiletype_shape::WALL ) {
out << "shape = " << (int32_t)shape2 << endl;
@ -427,15 +427,15 @@ cost_t getEdgeCostOld(color_ostream& out, df::coord pt1, df::coord pt2) {
cost += costWeight[CostDimension::Dig];
return cost;
}
//descending
if ( passable_high2 )
return cost;
if ( building2 || construction2 ) {
return -1;
}
//must be a wall?
if ( shape2 != df::enums::tiletype_shape::WALL ) {
out.print("%s, line %n: WTF?\n", __FILE__, __LINE__);
@ -445,7 +445,7 @@ cost_t getEdgeCostOld(color_ostream& out, df::coord pt1, df::coord pt2) {
cost += costWeight[CostDimension::Dig];
return cost;
}
//moving diagonally
return -1;
}
@ -455,7 +455,7 @@ vector<Edge>* getEdgeSet(color_ostream &out, df::coord point, MapExtras::MapCach
//vector<Edge>* result = new vector<Edge>(26);
vector<Edge>* result = new vector<Edge>();
result->reserve(26);
//size_t count = 0;
for ( int32_t dx = -1; dx <= 1; dx++ ) {
for ( int32_t dy = -1; dy <= 1; dy++ ) {

@ -56,7 +56,7 @@ public:
cost = -1;
}
Edge(const Edge& e): p1(e.p1), p2(e.p2), cost(e.cost) {
}
Edge(df::coord p1In, df::coord p2In, cost_t costIn): cost(costIn) {
if ( p2In < p1In ) {

@ -103,7 +103,7 @@ static void printAttributes(color_ostream &con, df::unit* cre, ostream& out) {
static void printTraits(color_ostream &con, df::unit* cre, ostream& out)
{
out << " <Traits>" << endl;
df::unit_soul * s = cre->status.current_soul;
if (s)
@ -120,7 +120,7 @@ static void printTraits(color_ostream &con, df::unit* cre, ostream& out)
}
*/
out << "</Trait>" << endl;
}
}
out << " </Traits>" << endl;
@ -189,7 +189,7 @@ static void export_dwarf(color_ostream &con, df::unit* cre, ostream& out) {
info += Translation::TranslateName(&cre->name, false);
info[0] = toupper(info[0]);
con.print("Exporting %s\n", info.c_str());
out << " <Creature>" << endl;
element("Name", info.c_str(), out);
element("Nickname", cre->name.nickname.c_str(), out);
@ -225,7 +225,7 @@ command_result export_dwarves (color_ostream &con, std::vector <std::string> & p
uint32_t civ = ui->civ_id;
outf << "<?xml version='1.0' encoding='ibm850'?>" << endl << "<Creatures>" << endl;
for (int i = 0; i < world->units.all.size(); ++i)
{
df::unit* cre = world->units.all[i];

@ -1720,8 +1720,8 @@ struct dwarf_monitor_hook : public df::viewscreen_dwarfmodest
ostringstream date_str;
auto month = World::ReadCurrentMonth() + 1;
auto day = World::ReadCurrentDay();
date_str << "Date:" << World::ReadCurrentYear() << "-" <<
((month < 10) ? "0" : "") << month << "-" <<
date_str << "Date:" << World::ReadCurrentYear() << "-" <<
((month < 10) ? "0" : "") << month << "-" <<
((day < 10) ? "0" : "") << day;
OutputString(COLOR_GREY, x, y, date_str.str());

@ -463,7 +463,7 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan
break;
case SC_WORLD_UNLOADED:
world_specific_hooks(out,false);
break;
default:
break;

@ -247,6 +247,6 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
" * 0 - Disable dwarf teleportation (default)\n"
" * 1 - Make dwarves teleport to their destinations instantly.\n"
));
return CR_OK;
}

@ -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);
}
}

@ -46,7 +46,7 @@ command_result df_fixdiplomats (color_ostream &out, vector<string> &parameters)
for (int j = 0; j < ent->positions.own.size(); j++)
{
pos = ent->positions.own[j];
if (pos->responsibilities[entity_position_responsibility::MAKE_INTRODUCTIONS] &&
if (pos->responsibilities[entity_position_responsibility::MAKE_INTRODUCTIONS] &&
pos->responsibilities[entity_position_responsibility::MAKE_PEACE_AGREEMENTS] &&
pos->responsibilities[entity_position_responsibility::MAKE_TOPIC_AGREEMENTS])
{

@ -126,7 +126,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
Gui::setCursorCoords(c_x - (prevX-x), c_y - (prevY-y), z);
//Save this round's stuff for next time so we can monitor for changes made by the user
prevX = x;
prevX = x;
prevY = y;
prevZ = z;
prevMenuWidth = menu_width;

@ -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
@ -54,34 +54,34 @@ DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCom
commands.push_back(PluginCommand("fortplan","Lay out buildings in your fortress based on a Quickfort-style CSV input file.",fortplan,false,
"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;
}

@ -108,7 +108,7 @@ static bool close_hotkeys_screen()
return false;
Screen::dismiss(Core::getTopViewscreen());
for_each_(sorted_keys, [] (const string &sym)
for_each_(sorted_keys, [] (const string &sym)
{ Core::getInstance().ClearKeyBindings(sym + "@dfhack/viewscreen_hotkeys"); });
sorted_keys.clear();
return true;
@ -147,7 +147,7 @@ public:
hotkeys_column.clear();
int max_key_length = 0;
for_each_(sorted_keys, [&] (const string &sym)
for_each_(sorted_keys, [&] (const string &sym)
{ if (sym.length() > max_key_length) { max_key_length = sym.length(); } });
int padding = max_key_length + 2;
@ -200,7 +200,7 @@ public:
x += 3;
OutputHotkeyString(x, y, "Invoke", "Enter or Hotkey");
x += 3;
OutputToggleString(x, y, "Show Usage", "u", show_usage);
@ -255,7 +255,7 @@ public:
}
}
virtual std::string getFocusString()
virtual std::string getFocusString()
{
return "viewscreen_hotkeys";
}

@ -31,9 +31,9 @@ command_result infiniteSky (color_ostream &out, std::vector <std::string> & para
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.push_back(PluginCommand(
"infiniteSky",
"infiniteSky",
"Creates new sky levels on request, or as you construct up.",
infiniteSky, false,
infiniteSky, false,
"Usage:\n"
" infiniteSky\n"
" creates one more z-level\n"
@ -88,7 +88,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
if ( mode.g_mode != df::enums::game_mode::DWARF )
return CR_OK;
}
if ( world->constructions.size() == constructionSize )
return CR_OK;
int32_t zNow = world->map.z_count_block;
@ -101,7 +101,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
///break;
}
constructionSize = world->constructions.size();
return CR_OK;
}
@ -152,7 +152,7 @@ void doInfiniteSky(color_ostream& out, int32_t howMany) {
delete[] world->map_extras.z_level_flags;
world->map_extras.z_level_flags = flags;
}
}
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)

@ -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);
@ -219,8 +219,8 @@ int coord_to_index_48(int x, int y) {
bool gather_embark_tile(int EmbX, int EmbY, EmbarkTile * tile, MapExtras::MapCache * MP) {
tile->set_is_valid(false);
tile->set_world_x(world->map.region_x + (EmbX/3));
tile->set_world_y(world->map.region_y + (EmbY/3));
tile->set_world_x(world->map.region_x + (EmbX/3));
tile->set_world_y(world->map.region_y + (EmbY/3));
tile->set_world_z(world->map.region_z + 1); //adding one because floors get shifted one downwards.
tile->set_current_year(*cur_year);
tile->set_current_season(*cur_season);
@ -245,7 +245,7 @@ bool gather_embark_tile_layer(int EmbX, int EmbY, int EmbZ, EmbarkTileLayer * ti
int num_valid_blocks = 0;
for(int yy = 0; yy < 3; yy++) {
for(int xx = 0; xx < 3; xx++) {
DFCoord current_coord, upper_coord;
DFCoord current_coord, upper_coord;
current_coord.x = EmbX+xx;
current_coord.y = EmbY+yy;
current_coord.z = EmbZ;
@ -283,7 +283,7 @@ bool gather_embark_tile_layer(int EmbX, int EmbY, int EmbZ, EmbarkTileLayer * ti
num_valid_blocks++;
}
else if(designation.bits.flow_size && (tileShapeBasic(tileShape(upper_tile)) != tiletype_shape_basic::Floor)) { //Contains either water or lava.
tile->set_mat_type_table(array_index, BasicMaterial::LIQUID);
tile->set_mat_type_table(array_index, BasicMaterial::LIQUID);
if(designation.bits.liquid_type) //Magma
tile->set_mat_subtype_table(array_index, LiquidType::MAGMA);
else //water
@ -291,29 +291,29 @@ bool gather_embark_tile_layer(int EmbX, int EmbY, int EmbZ, EmbarkTileLayer * ti
num_valid_blocks++;
}
else if(((tileShapeBasic(tileShape(tile_type)) != tiletype_shape_basic::Open) ||
(tileShapeBasic(tileShape(upper_tile)) == tiletype_shape_basic::Floor)) &&
((tileShapeBasic(tileShape(tile_type)) != tiletype_shape_basic::Floor) ||
(tileShapeBasic(tileShape(upper_tile)) == tiletype_shape_basic::Floor)) &&
((tileShapeBasic(tileShape(tile_type)) != tiletype_shape_basic::Floor) ||
(tileShapeBasic(tileShape(upper_tile)) == tiletype_shape_basic::Floor))) { //if the upper tile is a floor, we don't skip, otherwise we do.
if(actual_mat.mat_type == builtin_mats::INORGANIC) { //inorganic
tile->set_mat_type_table(array_index, BasicMaterial::INORGANIC);
tile->set_mat_type_table(array_index, BasicMaterial::INORGANIC);
tile->set_mat_subtype_table(array_index, actual_mat.mat_index);
}
else if(actual_mat.mat_type == 419) { //Growing plants
tile->set_mat_type_table(array_index, BasicMaterial::PLANT);
tile->set_mat_type_table(array_index, BasicMaterial::PLANT);
tile->set_mat_subtype_table(array_index, actual_mat.mat_index);
}
else if(actual_mat.mat_type >= 420) { //Wooden constructions. Different from growing plants.
tile->set_mat_type_table(array_index, BasicMaterial::WOOD);
tile->set_mat_type_table(array_index, BasicMaterial::WOOD);
tile->set_mat_subtype_table(array_index, actual_mat.mat_index);
}
else { //Unknown and unsupported stuff. Will just be drawn as grey.
tile->set_mat_type_table(array_index, BasicMaterial::OTHER);
tile->set_mat_type_table(array_index, BasicMaterial::OTHER);
tile->set_mat_subtype_table(array_index, actual_mat.mat_type);
}
num_valid_blocks++;
}
else {
tile->set_mat_type_table(array_index, BasicMaterial::AIR);
tile->set_mat_type_table(array_index, BasicMaterial::AIR);
}
}
}
@ -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);

@ -611,7 +611,7 @@ command_result df_liquids_execute(color_ostream &out, OperationMode &cur_mode, d
case M_KEEP:
{
auto bflags = (*biter)->BlockFlags();
out << "flow bit 1 = " << bflags.bits.update_liquid << endl;
out << "flow bit 1 = " << bflags.bits.update_liquid << endl;
out << "flow bit 2 = " << bflags.bits.update_liquid_twice << endl;
}
}

@ -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

@ -54,7 +54,7 @@ function BinaryPatch:apply()
if not self:test() then
error(string.format("pre-data for binary patch does not match expected"))
end
local post_buf=df.new('uint8_t',#self.pre_data)
for k,v in ipairs(self.pre_data) do
if self.data[k]==nil then
@ -83,7 +83,7 @@ function BinaryPatch:remove(delete)
error("can't remove BinaryPatch, not applied.")
end
local arr=ms.CheckedArray.new('uint8_t',self.address,self.address+#self.pre_data)
local post_buf=df.new('uint8_t',#self.pre_data)
for k,v in pairs(self.pre_data) do
post_buf[k-1]=v
@ -112,7 +112,7 @@ plugins=plugins or {}
BinaryPlugin=defclass(BinaryPlugin)
BinaryPlugin.ATTRS {filename=DEFAULT_NIL,reloc_table={},name=DEFAULT_NIL}
function BinaryPlugin:init(args)
end
function BinaryPlugin:postinit(args)
if self.name==nil then error("Not a valid plugin name!") end
@ -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)
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)
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
until ans~=nil and (ans<=#self.items and ans>0)
if type(self.items[ans][1])=="function" then
self.items[ans][1]()
else

@ -3,99 +3,99 @@ 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
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
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)
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()
local adv=df.global.world.units.active[0]
local wmap=df.global.world.map
local sub_pos={x=adv.pos.x,y=adv.pos.y,z=adv.pos.z}
local region_pos={x=wmap.region_x,y=wmap.region_y,z=wmap.region_z}

@ -14,7 +14,7 @@ if myos=="windows" then
error("caste and race count must be less then "..MAX_RACES)
end
local n_to_id=require("plugins.dfusion.tools").build_race_names()
local ids={}
for k,v in pairs(races) do
local race=v[1] or v
@ -30,7 +30,7 @@ if myos=="windows" then
if race_caste_data~=nil then
self:parseRaces(race_caste_data)
end
if stoff==nil then
error("address for start_dwarf_count not found!")
end
@ -41,8 +41,8 @@ if myos=="windows" then
for k,v in ipairs(tmp_table) do
table.insert(needle,v)
end
local mem=ms.get_code_segment()
local mem=ms.get_code_segment()
print(mem.uint8_t:addr2idx(stoff))
print(mem.uint8_t:find(needle,mem.uint8_t:addr2idx(stoff)))
local _,trg_offset=mem.uint8_t:find(needle,mem.uint8_t:addr2idx(stoff),nil)--maybe endoff=stoff+bignumber
@ -58,31 +58,31 @@ if myos=="windows" then
if caste_offset==nil or caste_offset-stoff>1000 then
error("Caste change code not found or found too far!")
end
self.disable_castes=self.disable_castes or dfu.BinaryPatch{pre_data={0x83,0xc8,0xff},data={0x90,0x90,0x90},address=caste_offset,name="custom_embark_caste_disable"}
self.disable_castes:apply()
self:setEmbarkParty(self.race_caste_data)
local caste_array=self:get_or_alloc("caste_array","uint16_t",MAX_RACES)
local race_array=self:get_or_alloc("race_array","uint16_t",MAX_RACES)
local race_array_off,caste_array_off
local _
_,race_array_off=df.sizeof(race_array)
_,caste_array_off=df.sizeof(caste_array)
self:set_marker_dword("race",caste_array_off) --hehe... mixed them up i guess...
self:set_marker_dword("caste",race_array_off)
self:move_to_df()
self.call_patch:apply()
self.installed=true
end
function CustomEmbark:setEmbarkParty(racesAndCastes)
local stoff=dfhack.internal.getAddress('start_dwarf_count')
if self.dwarfcount== nil then
self.dwarfcount=dfu.BinaryPatch{pre_data=dfu.dwordToTable(7),data=dfu.dwordToTable(#self.race_caste_data),address=stoff,name="custom_embark_embarkcount"}
self.dwarfcount:apply()
@ -91,7 +91,7 @@ if myos=="windows" then
end
local caste_array=self:get_or_alloc("caste_array","uint16_t",MAX_RACES)
local race_array=self:get_or_alloc("race_array","uint16_t",MAX_RACES)
for k,v in ipairs(self.race_caste_data) do
caste_array[k-1]=v[2] or -1
race_array[k-1]=v[1]

@ -13,7 +13,7 @@ function FriendshipRainbow:findall_needles(codesg,needle) -- todo move to memsca
local cidx,caddr=codesg.uint8_t:find(needle)
local ret={}
while cidx~=nil do
table.insert(ret,{cidx,caddr})
table.insert(ret,{cidx,caddr})
cidx,caddr=codesg.uint8_t:find(needle,cidx+1)
end
return ret
@ -23,10 +23,10 @@ function FriendshipRainbow:find_one(codesg,needle,crace)
return self:findall_needles(codesg,needle)
end
function FriendshipRainbow:find_all()
local code=ms.get_code_segment()
local code=ms.get_code_segment()
local locations={}
local _,crace=df.sizeof(df.global.ui:_field("race_id"))
dfu.concatTables(locations,self:find_one(code,{0x66,0xa1},crace)) --mov ax,[ptr]
dfu.concatTables(locations,self:find_one(code,{0xa1},crace)) --mov ax,[ptr]
local registers=
@ -40,11 +40,11 @@ function FriendshipRainbow:find_all()
--0x2d, --ebp not used?
}
for k,reg in ipairs(registers) do
dfu.concatTables(locations,self:find_one(code,{0x0f,0xbf,reg},crace)) --movsx reg,[ptr]
dfu.concatTables(locations,self:find_one(code,{0x66,0x8b,reg},crace)) --mov reg,[ptr]
end
return self:filter_locations(code,locations)
end
function FriendshipRainbow:filter_locations(codesg,locations)
@ -57,7 +57,7 @@ function FriendshipRainbow:filter_locations(codesg,locations)
0xb8,0xbb,0xb9,0xba,0xbe,0xbf}
for _,entry in ipairs(locations) do
for _,r in ipairs(registers) do
local idx,addr=codesg.uint8_t:find({0x39,r,0x8c,0x00,0x00,0x00},
codesg.uint8_t:addr2idx(entry[2]),codesg.uint8_t:addr2idx(entry[2])+MAX_CODE_DIST)
if addr then
@ -90,7 +90,7 @@ function FriendshipRainbow:set_races(arr)
local n_to_id=require("plugins.dfusion.tools").build_race_names()
local ids={}
for k,v in ipairs(self.race_data) do -- to check if all races are valid.
ids[k]=n_to_id[v]
ids[k]=n_to_id[v]
end
for k,v in ipairs(ids) do
arr[k-1]=ids[k]

@ -19,205 +19,205 @@ function build_race_names()
return RaceNames
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
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
end
menu:add("Set current race",setrace)
function GiveSentience(names)
local RaceTable=build_race_names() --slow.If loaded don't load again
function GiveSentience(names)
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
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
until id==nil
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.."...")
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
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
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
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
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
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
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")
end
@ -237,7 +237,7 @@ function powerup(unit,labor_rating,military_rating,skills)
end
utils.insert_or_update(unit.status.current_soul.skills, { new = true, id = sv, rating = new_rating, experience = (new_rating * 500) + (new_rating * (new_rating - 1)) * 50}, 'id')
end
end
menu:add("Power up",powerup)
return _ENV

@ -1,7 +1,7 @@
local _ENV = mkmodule('plugins.eventful')
--[[
--]]
local function getShopName(btype,bsubtype,bcustom)
local typenames_shop={[df.workshop_type.Carpenters]="CARPENTERS",[df.workshop_type.Farmers]="FARMERS",
@ -22,13 +22,13 @@ local function getShopName(btype,bsubtype,bcustom)
[df.furnace_type.MagmaGlassFurnace]="MAGMA_GLASS_FURNACE",[df.furnace_type.MagmaKiln]="MAGMA_KILN",
[df.furnace_type.Kiln]="KILN"}
if btype==df.building_type.Workshop then
if typenames_shop[bsubtype]~=nil then
if typenames_shop[bsubtype]~=nil then
return typenames_shop[bsubtype]
else
return df.building_def_workshopst.find(bcustom).code
end
elseif btype==df.building_type.Furnace then
if typenames_furnace[bsubtype]~=nil then
if typenames_furnace[bsubtype]~=nil then
return typenames_furnace[bsubtype]
else
return df.building_def_furnacest.find(bcustom).code

@ -62,7 +62,7 @@ function list_orders()
print("Stockpile #"..num, name, trigger)
listed = true
end
if not listed then
print("No manager jobs have been set for your stockpiles.")
print("Use j in a stockpile menu to create one...")
@ -79,7 +79,7 @@ function start_bookkeeping()
result[reaction_id] = amount
end
end
jobs_to_create = result
end
@ -89,7 +89,7 @@ function finish_bookkeeping()
for reaction, amount in pairs(jobs_to_create) do
create_orders(reaction_list[reaction].order, amount)
end
jobs_to_create = {}
end
@ -98,7 +98,7 @@ function stockpile_settings(sp)
if not order then
return "No job selected", ""
end
return order.entry.value, trigger_name(order)
end
@ -138,7 +138,7 @@ function collect_orders()
end
end
end
return result
end
@ -158,12 +158,12 @@ function reaction_entry(job_type, values, name)
mat_type = -1,
mat_index = -1,
}
if values then
-- Override default attributes.
order:assign(values)
end
return {
name = name or df.job_type.attrs[job_type].caption,
order = order,
@ -175,20 +175,20 @@ function resource_reactions(reactions, job_type, mat_info, keys, items, options)
for key, value in pairs(mat_info.management) do
values[key] = value
end
for _, itemid in ipairs(keys) do
local itemdef = items[itemid]
local start = options.verb or mat_info.verb or "Make"
if options.adjective then
start = start.." "..itemdef.adjective
end
if (not options.permissible) or options.permissible(itemdef) then
local item_name = " "..itemdef[options.name_field or "name"]
if options.capitalize then
item_name = string.gsub(item_name, " .", string.upper)
end
values.item_subtype = itemid
table.insert(reactions, reaction_entry(job_type, values, start.." "..mat_info.adjective..item_name))
end
@ -202,7 +202,7 @@ function material_reactions(reactions, itemtypes, mat_info)
if row[3] then
line = line.." "..row[3]
end
table.insert(reactions, reaction_entry(row[1], mat_info.management, line))
end
end
@ -225,38 +225,38 @@ function collect_reactions()
-- but I currently can only find it while the job selection screen is active.
-- Even that list doesn't seem to include their names.
local result = {}
-- A few task types are obsolete in newer DF versions.
local v34 = string.match(dfhack.getDFVersion(), "v0.34")
-- Caching the enumeration might not be important, but saves lookups.
local job_types = df.job_type
local materials = {
rock = {
adjective = "rock",
management = {mat_type = 0},
},
}
for _, name in ipairs{"wood", "cloth", "leather", "silk", "yarn", "bone", "shell", "tooth", "horn", "pearl"} do
materials[name] = {
adjective = name,
management = {material_category = {[name] = true}},
}
end
materials.wood.adjective = "wooden"
materials.tooth.adjective = "ivory/tooth"
materials.leather.clothing_flag = "LEATHER"
-- Collection and Entrapment
table.insert(result, reaction_entry(job_types.CollectWebs))
table.insert(result, reaction_entry(job_types.CollectSand))
table.insert(result, reaction_entry(job_types.CollectClay))
table.insert(result, reaction_entry(job_types.CatchLiveLandAnimal))
table.insert(result, reaction_entry(job_types.CatchLiveFish))
-- Cutting, encrusting, and metal extraction.
local rock_types = df.global.world.raws.inorganics
for rock_id = #rock_types-1, 0, -1 do
@ -267,35 +267,35 @@ function collect_reactions()
mat_type = 0,
mat_index = rock_id,
}, "Cut "..rock_name))
table.insert(result, reaction_entry(job_types.EncrustWithGems, {
mat_type = 0,
mat_index = rock_id,
item_category = {finished_goods = true},
}, "Encrust Finished Goods With "..rock_name))
table.insert(result, reaction_entry(job_types.EncrustWithGems, {
mat_type = 0,
mat_index = rock_id,
item_category = {furniture = true},
}, "Encrust Furniture With "..rock_name))
table.insert(result, reaction_entry(job_types.EncrustWithGems, {
mat_type = 0,
mat_index = rock_id,
item_category = {ammo = true},
}, "Encrust Ammo With "..rock_name))
end
if #rock_types[rock_id].metal_ore.mat_index > 0 then
table.insert(result, reaction_entry(job_types.SmeltOre, {mat_type = 0, mat_index = rock_id}, "Smelt "..rock_name.." Ore"))
end
if #rock_types[rock_id].thread_metal.mat_index > 0 then
table.insert(result, reaction_entry(job_types.ExtractMetalStrands, {mat_type = 0, mat_index = rock_id}))
end
end
-- Glass cutting and encrusting, with different job numbers.
-- We could search the entire table, but glass is less subject to raws.
local glass_types = df.global.world.raws.mat_table.builtin
@ -309,61 +309,61 @@ function collect_reactions()
adjective = glass_name,
management = {mat_type = glass_id},
})
table.insert(result, reaction_entry(job_types.CutGlass, {mat_type = glass_id}, "Cut "..glass_name))
table.insert(result, reaction_entry(job_types.EncrustWithGlass, {
mat_type = glass_id,
item_category = {finished_goods = true},
}, "Encrust Finished Goods With "..glass_name))
table.insert(result, reaction_entry(job_types.EncrustWithGlass, {
mat_type = glass_id,
item_category = {furniture = true},
}, "Encrust Furniture With "..glass_name))
table.insert(result, reaction_entry(job_types.EncrustWithGlass, {
mat_type = glass_id,
item_category = {ammo = true},
}, "Encrust Ammo With "..glass_name))
end
end
-- Dyeing
table.insert(result, reaction_entry(job_types.DyeThread))
table.insert(result, reaction_entry(job_types.DyeCloth))
-- Sew Image
local cloth_mats = {materials.cloth, materials.silk, materials.yarn, materials.leather}
for _, material in ipairs(cloth_mats) do
material_reactions(result, {{job_types.SewImage, "Sew", "Image"}}, material)
end
for _, spec in ipairs{materials.bone, materials.shell, materials.tooth, materials.horn, materials.pearl} do
material_reactions(result, {{job_types.DecorateWith, "Decorate With"}}, spec)
end
table.insert(result, reaction_entry(job_types.MakeTotem))
table.insert(result, reaction_entry(job_types.ButcherAnimal))
table.insert(result, reaction_entry(job_types.MillPlants))
table.insert(result, reaction_entry(job_types.MakePotashFromLye))
table.insert(result, reaction_entry(job_types.MakePotashFromAsh))
-- Kitchen
table.insert(result, reaction_entry(job_types.PrepareMeal, {mat_type = 2}, "Prepare Easy Meal"))
table.insert(result, reaction_entry(job_types.PrepareMeal, {mat_type = 3}, "Prepare Fine Meal"))
table.insert(result, reaction_entry(job_types.PrepareMeal, {mat_type = 4}, "Prepare Lavish Meal"))
if v34 then
-- Brew Drink
table.insert(result, reaction_entry(job_types.BrewDrink))
end
-- Weaving
table.insert(result, reaction_entry(job_types.WeaveCloth, {material_category = {plant = true}}, "Weave Thread into Cloth"))
table.insert(result, reaction_entry(job_types.WeaveCloth, {material_category = {silk = true}}, "Weave Thread into Silk"))
table.insert(result, reaction_entry(job_types.WeaveCloth, {material_category = {yarn = true}}, "Weave Yarn into Cloth"))
-- Extracts, farmer's workshop, and wood burning
table.insert(result, reaction_entry(job_types.ExtractFromPlants))
table.insert(result, reaction_entry(job_types.ExtractFromRawFish))
@ -382,7 +382,7 @@ function collect_reactions()
table.insert(result, reaction_entry(job_types.ProcessPlantsBarrel))
table.insert(result, reaction_entry(job_types.MakeCharcoal))
table.insert(result, reaction_entry(job_types.MakeAsh))
-- Reactions defined in the raws.
-- Not all reactions are allowed to the civilization.
-- That includes "Make sharp rock" by default.
@ -392,7 +392,7 @@ function collect_reactions()
local name = string.gsub(reaction.name, "^.", string.upper)
table.insert(result, reaction_entry(job_types.CustomReaction, {reaction_name = reaction.code}, name))
end
-- Metal forging
local itemdefs = df.global.world.raws.itemdefs
for rock_id = 0, #rock_types - 1 do
@ -403,76 +403,76 @@ function collect_reactions()
management = {mat_type = 0, mat_index = rock_id},
verb = "Forge",
}
if material.flags.IS_METAL then
table.insert(result, reaction_entry(job_types.StudWith, mat_flags.management, "Stud With "..rock_name))
if material.flags.ITEMS_WEAPON then
-- Todo: Are these really the right flags to check?
resource_reactions(result, job_types.MakeWeapon, mat_flags, entity.resources.weapon_type, itemdefs.weapons, {
permissible = (function(itemdef) return itemdef.skill_ranged == -1 end),
})
-- Is this entirely disconnected from the entity?
material_reactions(result, {{MakeBallistaArrowHead, "Forge", "Ballista Arrow Head"}}, mat_flags)
resource_reactions(result, job_types.MakeTrapComponent, mat_flags, entity.resources.trapcomp_type, itemdefs.trapcomps, {
adjective = true,
})
resource_reactions(result, job_types.AssembleSiegeAmmo, mat_flags, entity.resources.siegeammo_type, itemdefs.siege_ammo, {
verb = "Assemble",
})
end
if material.flags.ITEMS_WEAPON_RANGED then
resource_reactions(result, job_types.MakeWeapon, mat_flags, entity.resources.weapon_type, itemdefs.weapons, {
permissible = (function(itemdef) return itemdef.skill_ranged >= 0 end),
})
end
if material.flags.ITEMS_DIGGER then
-- Todo: Ranged or training digging weapons?
resource_reactions(result, job_types.MakeWeapon, mat_flags, entity.resources.digger_type, itemdefs.weapons, {
})
end
if material.flags.ITEMS_AMMO then
resource_reactions(result, job_types.MakeAmmo, mat_flags, entity.resources.ammo_type, itemdefs.ammo, {
name_field = "name_plural",
})
end
if material.flags.ITEMS_ANVIL then
material_reactions(result, {{job_types.ForgeAnvil, "Forge", "Anvil"}}, mat_flags)
end
if material.flags.ITEMS_ARMOR then
local metalclothing = (function(itemdef) return itemdef.props.flags.METAL end)
clothing_reactions(result, mat_flags, metalclothing)
resource_reactions(result, job_types.MakeShield, mat_flags, entity.resources.shield_type, itemdefs.shields, {
})
end
if material.flags.ITEMS_SOFT then
local metalclothing = (function(itemdef) return itemdef.props.flags.SOFT and not itemdef.props.flags.METAL end)
clothing_reactions(result, mat_flags, metalclothing)
end
if material.flags.ITEMS_HARD then
resource_reactions(result, job_types.MakeTool, mat_flags, entity.resources.tool_type, itemdefs.tools, {
permissible = (function(itemdef) return itemdef.flags.HARD_MAT end),
capitalize = true,
})
end
if material.flags.ITEMS_METAL then
resource_reactions(result, job_types.MakeTool, mat_flags, entity.resources.tool_type, itemdefs.tools, {
permissible = (function(itemdef) return itemdef.flags.METAL_MAT end),
capitalize = true,
})
end
if material.flags.ITEMS_HARD then
material_reactions(result, {
{job_types.ConstructDoor, "Construct", "Door"},
@ -505,7 +505,7 @@ function collect_reactions()
{job_types.MakeCrafts, "Make", "Crafts"},
}, mat_flags)
end
if material.flags.ITEMS_SOFT then
material_reactions(result, {
{job_types.MakeBackpack, "Make", "Backpack"},
@ -516,26 +516,26 @@ function collect_reactions()
end
end
end
-- Traction Bench
table.insert(result, reaction_entry(job_types.ConstructTractionBench))
-- Non-metal weapons
resource_reactions(result, job_types.MakeWeapon, materials.wood, entity.resources.weapon_type, itemdefs.weapons, {
permissible = (function(itemdef) return itemdef.skill_ranged >= 0 end),
})
resource_reactions(result, job_types.MakeWeapon, materials.wood, entity.resources.training_weapon_type, itemdefs.weapons, {
})
resource_reactions(result, job_types.MakeWeapon, materials.bone, entity.resources.weapon_type, itemdefs.weapons, {
permissible = (function(itemdef) return itemdef.skill_ranged >= 0 end),
})
resource_reactions(result, job_types.MakeWeapon, materials.rock, entity.resources.weapon_type, itemdefs.weapons, {
permissible = (function(itemdef) return itemdef.flags.CAN_STONE end),
})
-- Wooden items
-- Closely related to the ITEMS_HARD list.
material_reactions(result, {
@ -552,12 +552,12 @@ function collect_reactions()
{job_types.MakeGoblet, "Make", "Cup"},
{job_types.MakeInstrument, "Make", "Instrument"},
}, materials.wood)
resource_reactions(result, job_types.MakeTool, materials.wood, entity.resources.tool_type, itemdefs.tools, {
-- permissible = (function(itemdef) return itemdef.flags.WOOD_MAT end),
capitalize = true,
})
material_reactions(result, {
{job_types.MakeToy, "Make", "Toy"},
{job_types.ConstructBlocks, "Construct", "Blocks"},
@ -570,12 +570,12 @@ function collect_reactions()
{job_types.MakeCage, "Make", "Cage"},
{job_types.MakePipeSection, "Make", "Pipe Section"},
}, materials.wood)
resource_reactions(result, job_types.MakeTrapComponent, materials.wood, entity.resources.trapcomp_type, itemdefs.trapcomps, {
permissible = (function(itemdef) return itemdef.flags.WOOD end),
adjective = true,
})
-- Rock items
material_reactions(result, {
{job_types.ConstructDoor, "Construct", "Door"},
@ -591,12 +591,12 @@ function collect_reactions()
{job_types.MakeGoblet, "Make", "Mug"},
{job_types.MakeInstrument, "Make", "Instrument"},
}, materials.rock)
resource_reactions(result, job_types.MakeTool, materials.rock, entity.resources.tool_type, itemdefs.tools, {
permissible = (function(itemdef) return itemdef.flags.HARD_MAT end),
capitalize = true,
})
material_reactions(result, {
{job_types.MakeToy, "Make", "Toy"},
{job_types.ConstructQuern, "Construct", "Quern"},
@ -605,7 +605,7 @@ function collect_reactions()
{job_types.ConstructStatue, "Construct", "Statue"},
{job_types.ConstructBlocks, "Construct", "Blocks"},
}, materials.rock)
-- Glass items
for _, mat_info in ipairs(glasses) do
material_reactions(result, {
@ -622,12 +622,12 @@ function collect_reactions()
{job_types.MakeGoblet, "Make", "Goblet"},
{job_types.MakeInstrument, "Make", "Instrument"},
}, mat_info)
resource_reactions(result, job_types.MakeTool, mat_info, entity.resources.tool_type, itemdefs.tools, {
permissible = (function(itemdef) return itemdef.flags.HARD_MAT end),
capitalize = true,
})
material_reactions(result, {
{job_types.MakeToy, "Make", "Toy"},
{job_types.ConstructStatue, "Construct", "Statue"},
@ -635,44 +635,44 @@ function collect_reactions()
{job_types.MakeCage, "Make", "Terrarium"},
{job_types.MakePipeSection, "Make", "Tube"},
}, mat_info)
resource_reactions(result, job_types.MakeTrapComponent, mat_info, entity.resources.trapcomp_type, itemdefs.trapcomps, {
adjective = true,
})
end
-- Bed, specified as wooden.
table.insert(result, reaction_entry(job_types.ConstructBed, materials.wood.management))
-- Windows
for _, mat_info in ipairs(glasses) do
material_reactions(result, {
{job_types.MakeWindow, "Make", "Window"},
}, mat_info)
end
-- Rock Mechanisms
table.insert(result, reaction_entry(job_types.ConstructMechanisms, materials.rock.management))
resource_reactions(result, job_types.AssembleSiegeAmmo, materials.wood, entity.resources.siegeammo_type, itemdefs.siege_ammo, {
verb = "Assemble",
})
for _, mat_info in ipairs(glasses) do
material_reactions(result, {
{job_types.MakeRawGlass, "Make Raw", nil},
}, mat_info)
end
material_reactions(result, {
{job_types.MakeBackpack, "Make", "Backpack"},
{job_types.MakeQuiver, "Make", "Quiver"},
}, materials.leather)
for _, material in ipairs(cloth_mats) do
clothing_reactions(result, material, (function(itemdef) return itemdef.props.flags[material.clothing_flag or "SOFT"] end))
end
-- Boxes, Bags, and Ropes
local boxmats = {
{mats = {materials.wood}, box = "Chest"},
@ -693,7 +693,7 @@ function collect_reactions()
end
end
end
for _, mat in ipairs{
materials.wood,
materials.rock,
@ -709,28 +709,28 @@ function collect_reactions()
} do
material_reactions(result, {{job_types.MakeCrafts, "Make", "Crafts"}}, mat)
end
-- Siege engine parts
table.insert(result, reaction_entry(job_types.ConstructCatapultParts, materials.wood.management))
table.insert(result, reaction_entry(job_types.ConstructBallistaParts, materials.wood.management))
for _, mat in ipairs{materials.wood, materials.bone} do
resource_reactions(result, job_types.MakeAmmo, mat, entity.resources.ammo_type, itemdefs.ammo, {
name_field = "name_plural",
})
end
-- BARRED and SCALED as flag names don't quite seem to fit, here.
clothing_reactions(result, materials.bone, (function(itemdef) return itemdef.props.flags.BARRED end))
clothing_reactions(result, materials.shell, (function(itemdef) return itemdef.props.flags.SCALED end))
for _, mat in ipairs{materials.wood, materials.leather} do
resource_reactions(result, job_types.MakeShield, mat, entity.resources.shield_type, itemdefs.shields, {})
end
-- Melt a Metal Object
table.insert(result, reaction_entry(job_types.MeltMetalObject))
return result
end
@ -782,7 +782,7 @@ function screen:onInput(keys)
self.search_string = self.search_string .. string.upper(char)
end
end
self:refilter()
end
@ -799,7 +799,7 @@ function matchall(haystack, needles)
return false
end
end
return true
end
@ -815,16 +815,16 @@ function splitstring(full, pattern)
elseif start > n then
result[#result+1] = string.sub(full, n, start - 1)
end
if stop < n then
-- The pattern matches an empty string.
-- Avoid an infinite loop.
break
end
n = stop + 1
end
return result
end
@ -839,18 +839,18 @@ function screen:refilter()
}
end
end
if self.position < 1 then
self.position = #filtered
elseif self.position > #filtered then
self.position = 1
end
local start = 1
while self.position >= start + PageSize*2 do
start = start + PageSize*2
end
local displayed = {}
for n = 0, PageSize*2 - 1 do
local item = filtered[start + n]
@ -858,7 +858,7 @@ function screen:refilter()
break
end
local name = item.name
local x = 1
local y = FirstRow + n
if n >= PageSize then
@ -866,12 +866,12 @@ function screen:refilter()
y = y - PageSize
name = " "..name
end
local color = COLOR_CYAN
if start + n == self.position then
color = COLOR_LIGHTCYAN
end
displayed[n + 1] = {
x = x,
y = y,
@ -879,7 +879,7 @@ function screen:refilter()
color = color,
}
end
self.reactions = filtered
self.displayed = displayed
end
@ -917,18 +917,18 @@ function orders_match(a, b)
"mat_type",
"mat_index",
}
for _, fieldname in ipairs(fields) do
if a[fieldname] ~= b[fieldname] then
return false
end
end
local subtables = {
"item_category",
"material_category",
}
for _, fieldname in ipairs(subtables) do
local aa = a[fieldname]
local bb = b[fieldname]
@ -938,7 +938,7 @@ function orders_match(a, b)
end
end
end
return true
end
@ -953,13 +953,13 @@ function order_quantity(order, quantity)
end
end
end
if amount > 30 then
-- Respect the quantity limit.
-- With this many in the queue, we can wait for the next cycle.
return 30
end
return amount
end
@ -993,7 +993,7 @@ function countContents(container, settings)
total = total + 1
end
end
return total
end
@ -1009,7 +1009,7 @@ function check_stockpiles(verbose)
result[reaction] = (result[reaction] or 0) + amount
end
end
return result
end
@ -1030,7 +1030,7 @@ function check_pile(sp, verbose)
end
end
end
for _, item in ipairs(dfhack.buildings.getStockpileContents(sp)) do
if item:isAssignedToThisStockpile(sp.id) then
-- This is a bin or barrel associated with the stockpile.
@ -1039,14 +1039,14 @@ function check_pile(sp, verbose)
filled = filled + 1
end
end
if verbose then
print("Stockpile #"..sp.stockpile_number,
string.format("%3d spaces", numspaces),
string.format("%4d items", filled),
string.format("%4d empty spaces", empty))
end
return filled, empty
end
@ -1094,7 +1094,7 @@ function matches_stockpile(item, settings)
elseif df.item_threadst:is_instance(item) then
return settings.flags.cloth
end
return true
end

@ -149,7 +149,7 @@ command_result mapexport (color_ostream &out, std::vector <std::string> & parame
protomap.set_z_size(z_max);
out << "Writing material dictionary..." << std::endl;
for (size_t i = 0; i < world->raws.inorganics.size(); i++)
{
dfproto::Material *protomaterial = protomap.add_inorganic_material();
@ -173,10 +173,10 @@ command_result mapexport (color_ostream &out, std::vector <std::string> & parame
constructionMaterials[construction->pos] = std::make_pair(construction->mat_index, construction->mat_type);
}
}
coded_output->WriteVarint32(protomap.ByteSize());
protomap.SerializeToCodedStream(coded_output);
DFHack::t_feature blockFeatureGlobal;
DFHack::t_feature blockFeatureLocal;
@ -239,7 +239,7 @@ command_result mapexport (color_ostream &out, std::vector <std::string> & parame
prototile->set_tile_material(toProto(tileMaterial(type)));
df::coord map_pos = df::coord(b_x*16+x,b_y*16+y,z);
switch (tileMaterial(type))
{
case tiletype_material::SOIL:
@ -300,7 +300,7 @@ command_result mapexport (color_ostream &out, std::vector <std::string> & parame
}
}
}
coded_output->WriteVarint32(protoblock.ByteSize());
protoblock.SerializeToCodedStream(coded_output);
} // block x

@ -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;

@ -49,7 +49,7 @@ DFhackCExport command_result plugin_onupdate(color_ostream& out) {
}
return CR_OK;
}
if ( !wasLoaded ) {
wasLoaded = true;
}
@ -59,7 +59,7 @@ DFhackCExport command_result plugin_onupdate(color_ostream& out) {
return CR_OK;
}
count = 0;
int32_t race_id = ui->race_id;
int32_t civ_id = ui->civ_id;
for ( size_t a = 0; a < world->units.all.size(); a++ ) {
@ -69,7 +69,7 @@ DFhackCExport command_result plugin_onupdate(color_ostream& out) {
continue;
if ( unit->flags1.bits.dead )
continue;
int processedThoughtCount;
map<int,int>::iterator i = processedThoughtCountTable.find(unit->id);
if ( i == processedThoughtCountTable.end() ) {
@ -78,13 +78,13 @@ DFhackCExport command_result plugin_onupdate(color_ostream& out) {
} else {
processedThoughtCount = (*i).second;
}
if ( processedThoughtCount == unit->status.recent_events.size() ) {
continue;
} else if ( processedThoughtCount > unit->status.recent_events.size() ) {
processedThoughtCount = unit->status.recent_events.size();
}
//don't reprocess any old thoughts
vector<df::unit_thought*> newThoughts;
for ( size_t b = processedThoughtCount; b < unit->status.recent_events.size(); b++ ) {
@ -120,7 +120,7 @@ DFhackCExport command_result plugin_onupdate(color_ostream& out) {
}
processedThoughtCountTable[unit->id] = unit->status.recent_events.size();
}
return CR_OK;
}
@ -159,11 +159,11 @@ command_result misery(color_ostream &out, vector<string>& parameters) {
out.printerr("misery can only be enabled in fortress mode with a fully-loaded game.\n");
return CR_FAILURE;
}
if ( parameters.size() < 1 || parameters.size() > 2 ) {
return CR_WRONG_USAGE;
}
if ( parameters[0] == "disable" ) {
if ( parameters.size() > 1 ) {
return CR_WRONG_USAGE;
@ -197,7 +197,7 @@ command_result misery(color_ostream &out, vector<string>& parameters) {
factor = a;
is_enabled = factor > 1;
}
return CR_OK;
}

@ -90,7 +90,7 @@ void impregnateMany() {
else
females[unit->race].push_back(a);
}
for ( auto i = females.begin(); i != females.end(); i++ ) {
int32_t race = i->first;
vector<int32_t>& femalesList = i->second;
@ -99,10 +99,10 @@ void impregnateMany() {
break;
vector<int32_t> compatibles;
df::coord pos1 = units[femalesList[a]]->pos;
if ( males.find(i->first) == males.end() )
continue;
vector<int32_t>& malesList = males[i->first];
for ( size_t b = 0; b < malesList.size(); b++ ) {
df::coord pos2 = units[malesList[b]]->pos;
@ -111,7 +111,7 @@ void impregnateMany() {
}
if ( compatibles.empty() )
continue;
size_t maleIndex = (size_t)(compatibles.size()*((float)rand() / (1+(float)RAND_MAX)));
if ( impregnate(units[femalesList[a]], units[compatibles[maleIndex]]) )
popcount[race]++;
@ -124,7 +124,7 @@ bool impregnate(df::unit* female, df::unit* male) {
return false;
if ( female->relations.pregnancy_genes )
return false;
df::unit_genes* preg = new df::unit_genes;
*preg = male->appearance.genes;
female->relations.pregnancy_genes = preg;
@ -138,7 +138,7 @@ void tickHandler(color_ostream& out, void* data) {
return;
CoreSuspender suspend;
impregnateMany();
EventManager::unregisterAll(plugin_self);
EventManager::EventHandler handle(tickHandler, howOften);
EventManager::registerTick(handle, howOften, plugin_self);
@ -147,7 +147,7 @@ void tickHandler(color_ostream& out, void* data) {
command_result petcapRemover (color_ostream &out, std::vector <std::string> & parameters)
{
CoreSuspender suspend;
for ( size_t a = 0; a < parameters.size(); a++ ) {
if ( parameters[a] == "every" ) {
if ( a+1 >= parameters.size() )
@ -186,18 +186,18 @@ command_result petcapRemover (color_ostream &out, std::vector <std::string> & pa
out.print("%s, line %d: invalid argument: %s\n", __FILE__, __LINE__, parameters[a].c_str());
return CR_WRONG_USAGE;
}
if ( howOften < 0 ) {
is_enabled = false;
return CR_OK;
}
is_enabled = true;
EventManager::unregisterAll(plugin_self);
EventManager::EventHandler handle(tickHandler, howOften);
EventManager::registerTick(handle, howOften, plugin_self);
out.print("petcapRemover: howOften = every %d ticks, popcap per species = %d, preg time = %d ticks.\n", howOften, popcap, pregtime);
return CR_OK;
}

@ -84,7 +84,7 @@ command_result df_cprobe (color_ostream &out, vector <string> & parameters)
if(unit->pos.x == cursorX && unit->pos.y == cursorY && unit->pos.z == cursorZ)
{
out.print("Creature %d, race %d (%x), civ %d (%x)\n", unit->id, unit->race, unit->race, unit->civ_id, unit->civ_id);
for(size_t j=0; j<unit->inventory.size(); j++)
{
df::unit_inventory_item* inv_item = unit->inventory[j];
@ -101,7 +101,7 @@ command_result df_cprobe (color_ostream &out, vector <string> & parameters)
out << endl;
}
}
// don't leave loop, there may be more than 1 creature at the cursor position
//break;
}
@ -242,7 +242,7 @@ command_result df_probe (color_ostream &out, vector <string> & parameters)
const char* surroundings[] = { "Serene", "Mirthful", "Joyous Wilds", "Calm", "Wilderness", "Untamed Wilds", "Sinister", "Haunted", "Terrifying" };
// biome, geolayer
out << "biome: " << des.bits.biome << " (" <<
out << "biome: " << des.bits.biome << " (" <<
"region id=" << biome->region_id << ", " <<
surroundings[surr] << ", " <<
"savagery " << biome->savagery << ", " <<
@ -345,7 +345,7 @@ command_result df_probe (color_ostream &out, vector <string> & parameters)
out << "no grow" << endl;
for(size_t e=0; e<block.block_events.size(); e++)
{
{
df::block_square_event * blev = block.block_events[e];
df::block_square_event_type blevtype = blev->getType();
switch(blevtype)

@ -153,7 +153,7 @@ void printMats(color_ostream &con, MatMap &mat, std::vector<T*> &materials, bool
{
if(it->first >= materials.size())
{
con << "Bad index: " << it->first << " out of "
con << "Bad index: " << it->first << " out of "
<< materials.size() << endl;
continue;
}

@ -4,205 +4,205 @@ package RemoteFortressReader;
option optimize_for = LITE_RUNTIME;
//We use shapes, etc, because the actual tiletypes may differ between DF versions.
enum TiletypeShape
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
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
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;
}

@ -60,7 +60,7 @@ command_result df_regrass (color_ostream &out, vector <string> & parameters)
// check block for grass events before looking at 16x16 tiles
df::block_square_event_grassst * grev = NULL;
for(size_t e=0; e<cur->block_events.size(); e++)
{
{
df::block_square_event * blev = cur->block_events[e];
df::block_square_event_type blevtype = blev->getType();
if(blevtype == df::block_square_event_type::grass)
@ -103,7 +103,7 @@ command_result df_regrass (color_ostream &out, vector <string> & parameters)
if(max)
{
for(size_t e=0; e<cur->block_events.size(); e++)
{
{
df::block_square_event * blev = cur->block_events[e];
df::block_square_event_type blevtype = blev->getType();
if(blevtype == df::block_square_event_type::grass)
@ -118,7 +118,7 @@ command_result df_regrass (color_ostream &out, vector <string> & parameters)
// try to find the 'original' event
bool regrew = false;
for(size_t e=0; e<cur->block_events.size(); e++)
{
{
df::block_square_event * blev = cur->block_events[e];
df::block_square_event_type blevtype = blev->getType();
if(blevtype == df::block_square_event_type::grass)
@ -138,7 +138,7 @@ command_result df_regrass (color_ostream &out, vector <string> & parameters)
{
vector <df::block_square_event_grassst *> gr_evs;
for(size_t e=0; e<cur->block_events.size(); e++)
{
{
df::block_square_event * blev = cur->block_events[e];
df::block_square_event_type blevtype = blev->getType();
if(blevtype == df::block_square_event_type::grass)

@ -79,7 +79,7 @@ rect2d getMapViewport()
}
else
return mkrect_wh(0,0,0,0);
}
int w=gps->dimx;
int h=gps->dimy;
@ -88,7 +88,7 @@ rect2d getMapViewport()
int menu_x2=w-MENU_WIDTH-2;
int menu_x1=area_x2-MENU_WIDTH-1;
int view_rb=w-1;
int area_pos=*df::global::ui_area_map_width;
int menu_pos=*df::global::ui_menu_width;
if(area_pos<3)
@ -97,7 +97,7 @@ rect2d getMapViewport()
}
if (menu_pos<area_pos || df::global::ui->main.mode!=0)
{
if (menu_pos >= area_pos)
if (menu_pos >= area_pos)
menu_pos = area_pos-1;
int menu_x = menu_x2;
if(menu_pos < 2) menu_x = menu_x1;
@ -128,7 +128,7 @@ void lightingEngineViewscreen::reinit()
void plotCircle(int xm, int ym, int r,const std::function<void(int,int)>& setPixel)
{
int x = -r, y = 0, err = 2-2*r; /* II. Quadrant */
int x = -r, y = 0, err = 2-2*r; /* II. Quadrant */
do {
setPixel(xm-x, ym+y); /* I. Quadrant */
setPixel(xm-y, ym-x); /* II. Quadrant */
@ -156,7 +156,7 @@ void plotSquare(int xm, int ym, int r,const std::function<void(int,int)>& setPix
void plotLine(int x0, int y0, int x1, int y1,rgbf power,const std::function<rgbf(rgbf,int,int,int,int)>& setPixel)
{
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
int err = dx+dy, e2; /* error value e_xy */
int rdx=0;
int rdy=0;
@ -177,9 +177,9 @@ void plotLine(int x0, int y0, int x1, int y1,rgbf power,const std::function<rgbf
}
void plotLineDiffuse(int x0, int y0, int x1, int y1,rgbf power,int num_diffuse,const std::function<rgbf(rgbf,int,int,int,int)>& setPixel,bool skip_hack=false)
{
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
int dsq=dx*dx+dy*dy;
int err = dx+dy, e2; /* error value e_xy */
int rdx=0;
@ -214,7 +214,7 @@ void plotLineDiffuse(int x0, int y0, int x1, int y1,rgbf power,int num_diffuse,c
void plotLineAA(int x0, int y0, int x1, int y1,rgbf power,const std::function<rgbf(rgbf,int,int,int,int)>& setPixelAA)
{
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
int err = dx-dy, e2, x2; /* error value e_xy */
int ed = dx+dy == 0 ? 1 : sqrt((float)dx*dx+(float)dy*dy);
int rdx=0;
@ -232,7 +232,7 @@ void plotLineAA(int x0, int y0, int x1, int y1,rgbf power,const std::function<rg
rdx=rdy=0;
if (2*e2 >= -dx) { /* x step */
if (x0 == x1) break;
if (e2+dy < ed)
{
str=1-(e2+dy)/(float)ed;
@ -240,11 +240,11 @@ void plotLineAA(int x0, int y0, int x1, int y1,rgbf power,const std::function<rg
strsum+=str;
}
err -= dy; x0 += sx; rdx=sx;
}
}
if (2*e2 <= dy) { /* y step */
if (y0 == y1) break;
if (dx-e2 < ed)
if (dx-e2 < ed)
{
str=1-(dx-e2)/(float)ed;
sumPower+=setPixelAA(power*str,lrdx,lrdy,x2+sx,y0);
@ -320,16 +320,16 @@ void lightingEngineViewscreen::updateWindow()
else
std::swap(lightMap,myRenderer->lightGrid);
rect2d vp=getMapViewport();
myRenderer->invalidateRect(vp.first.x,vp.first.y,vp.second.x-vp.first.x,vp.second.y-vp.first.y);
}
void lightingEngineViewscreen::preRender()
{
}
void lightingEngineViewscreen::fixAdvMode(int mode)
{
MapExtras::MapCache mc;
const rgbf dim(levelDim,levelDim,levelDim);
rect2d vp=getMapViewport();
@ -413,7 +413,7 @@ matLightDef* lightingEngineViewscreen::getMaterialDef( int matType,int matIndex
auto it=matDefs.find(std::make_pair(matType,matIndex));
if(it!=matDefs.end())
return &it->second;
else
else
return NULL;
}
buildingLightDef* lightingEngineViewscreen::getBuildingDef( df::building* bld )
@ -421,7 +421,7 @@ buildingLightDef* lightingEngineViewscreen::getBuildingDef( df::building* bld )
auto it=buildingDefs.find(std::make_tuple((int)bld->getType(),(int)bld->getSubtype(),(int)bld->getCustomType()));
if(it!=buildingDefs.end())
return &it->second;
else
else
return NULL;
}
creatureLightDef* lightingEngineViewscreen::getCreatureDef(df::unit* u)
@ -502,10 +502,10 @@ rgbf lightingEngineViewscreen::propogateSun(MapExtras::Block* b, int x,int y,con
else if(basicShapeIce==df::tiletype_shape_basic::Floor || basicShapeIce==df::tiletype_shape_basic::Ramp || shapeIce==df::tiletype_shape::STAIR_UP)
if(!lastLevel)
ret*=matIce.transparency.pow(1.0f/7.0f);
}
}
lightDef=getMaterialDef(mat.mat_type,mat.mat_index);
if(!lightDef || !lightDef->isTransparent)
lightDef=&matWall;
if(basic_shape==df::tiletype_shape_basic::Wall)
@ -514,9 +514,9 @@ rgbf lightingEngineViewscreen::propogateSun(MapExtras::Block* b, int x,int y,con
}
else if(basic_shape==df::tiletype_shape_basic::Floor || basic_shape==df::tiletype_shape_basic::Ramp || shape==df::tiletype_shape::STAIR_UP)
{
if(!lastLevel)
ret*=lightDef->transparency.pow(1.0f/7.0f);
ret*=lightDef->transparency.pow(1.0f/7.0f);
}
else if(shape==df::tiletype_shape::STAIR_DOWN || shape==df::tiletype_shape::STAIR_UPDOWN)
{
@ -574,7 +574,7 @@ void lightingEngineViewscreen::doSun(const lightSource& sky,MapExtras::MapCache&
rgbf& curCell=cellArray[block_x][block_y];
curCell=propogateSun(b,block_x,block_y,curCell,z==window_z);
if(curCell.dot(curCell)<0.003f)
emptyCell++;
emptyCell++;
}
}
if(emptyCell==256)
@ -622,10 +622,10 @@ void lightingEngineViewscreen::doOcupancyAndLights()
}
else
daycol= fmod(dayHour,24.0f)/24.0f; //1->12h 0->24h
rgbf sky_col=getSkyColor(daycol);
lightSource sky(sky_col, -1);//auto calculate best size
MapExtras::MapCache cache;
doSun(sky,cache);
@ -640,7 +640,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
blockVp.second=(window2d+vpSize)/16;
blockVp.second.x=std::min(blockVp.second.x,(int16_t)df::global::world->map.x_count_block);
blockVp.second.y=std::min(blockVp.second.y,(int16_t)df::global::world->map.y_count_block);
for(int blockX=blockVp.first.x;blockX<=blockVp.second.x;blockX++)
for(int blockY=blockVp.first.y;blockY<=blockVp.second.y;blockY++)
{
@ -648,7 +648,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
MapExtras::Block* bDown=cache.BlockAt(DFCoord(blockX,blockY,window_z-1));
if(!b)
continue; //empty blocks fixed by sun propagation
for(int block_x = 0; block_x < 16; block_x++)
for(int block_y = 0; block_y < 16; block_y++)
{
@ -662,7 +662,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
int tile=getIndex(pos.x,pos.y);
rgbf& curCell=ocupancy[tile];
curCell=matAmbience.transparency;
df::tiletype type = b->tiletypeAt(gpos);
df::tile_designation d = b->DesignationAt(gpos);
@ -677,9 +677,9 @@ void lightingEngineViewscreen::doOcupancyAndLights()
bool is_floor=!ENUM_ATTR(tiletype_shape,passable_low,shape);
df::tiletype_shape_basic basic_shape = ENUM_ATTR(tiletype_shape, basic_shape, shape);
df::tiletype_material tileMat= ENUM_ATTR(tiletype,material,type);
DFHack::t_matpair mat=b->staticMaterialAt(gpos);
matLightDef* lightDef=getMaterialDef(mat.mat_type,mat.mat_index);
if(!lightDef || !lightDef->isTransparent)
lightDef=&matWall;
@ -698,7 +698,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
{
applyMaterial(tile,matWater, (float)d.bits.flow_size/7.0f, (float)d.bits.flow_size/7.0f);
}
if(d.bits.liquid_type && d.bits.flow_size>0)
if(d.bits.liquid_type && d.bits.flow_size>0)
{
applyMaterial(tile,matLava,(float)d.bits.flow_size/7.0f,(float)d.bits.flow_size/7.0f);
}
@ -713,10 +713,10 @@ void lightingEngineViewscreen::doOcupancyAndLights()
}
}
}
}
df::map_block* block=b->getRaw();
if(!block)
continue;
@ -749,7 +749,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
}
}
}
//blood and other goo
for(int i=0;i<block->block_events.size();i++)
{
@ -829,12 +829,12 @@ void lightingEngineViewscreen::doOcupancyAndLights()
}
}
}
//buildings
for(size_t i = 0; i < df::global::world->buildings.all.size(); i++)
{
df::building *bld = df::global::world->buildings.all[i];
if(window_z!=bld->z)
continue;
if(bld->getBuildStage()<bld->getMaxBuildStage()) //only work if fully built
@ -846,7 +846,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
p2=worldToViewportCoord(p2,vp,window2d);
if(isInRect(p1,vp)||isInRect(p2,vp))
{
int tile;
if(isInRect(p1,vp))
tile=getIndex(p1.x,p1.y); //TODO multitile buildings. How they would work?
@ -868,8 +868,8 @@ void lightingEngineViewscreen::doOcupancyAndLights()
if(!gate->gate_flags.bits.closed)
continue;
}
if(def->useMaterial)
{
matLightDef* mat=getMaterialDef(bld->mat_type,bld->mat_index);
@ -903,7 +903,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
}
}
}
}
rgbf lua_parseLightCell(lua_State* L)
{
@ -937,7 +937,7 @@ rgbf lua_parseLightCell(lua_State* L)
lua_pop(L,1)
matLightDef lua_parseMatDef(lua_State* L)
{
matLightDef ret;
lua_getfield(L,-1,"tr");
if(ret.isTransparent=!lua_isnil(L,-1))
@ -987,7 +987,7 @@ int lightingEngineViewscreen::parseMaterials(lua_State* L)
int index=lua_tonumber(L,-2);
//os->print("\tProcessing index:%d\n",index);
engine->matDefs[std::make_pair(type,index)]=lua_parseMatDef(L);
lua_pop(L, 1);
}
lua_pop(L, 1);
@ -1174,17 +1174,17 @@ void lightingEngineViewscreen::loadSettings()
std::string rawFolder;
if(df::global::world->cur_savegame.save_dir!="")
{
rawFolder= "data/save/" + (df::global::world->cur_savegame.save_dir) + "/raw/";
rawFolder= "data/save/" + (df::global::world->cur_savegame.save_dir) + "/raw/";
}
else
{
rawFolder= "raw/";
rawFolder= "raw/";
}
const std::string settingsfile=rawFolder+"rendermax.lua";
CoreSuspender lock;
color_ostream_proxy out(Core::getInstance().getConsole());
lua_State* s=DFHack::Lua::Core::State;
lua_newtable(s);
int env=lua_gettop(s);
@ -1202,7 +1202,7 @@ void lightingEngineViewscreen::loadSettings()
else
{
lua_pushvalue(s,env);
if(Lua::SafeCall(out,s,1,0))
{
lua_pushcfunction(s, parseMaterials);
@ -1235,7 +1235,7 @@ void lightingEngineViewscreen::loadSettings()
Lua::SafeCall(out,s,2,0);
out.print("%d items loaded\n",itemDefs.size());
}
}
}
catch(std::exception& e)
@ -1272,8 +1272,8 @@ void lightThread::run()
if(dispatch.occlusion.size()!=canvas.size()) //oh no somebody resized stuff
canvas.resize(dispatch.occlusion.size());
}
{ //get my rectangle (any will do)
tthread::lock_guard<tthread::mutex> guard(dispatch.unprocessedMutex);
if (dispatch.unprocessed.size()==0)
@ -1287,13 +1287,13 @@ void lightThread::run()
{
dispatch.occlusionReady=false;
}
}
work();
{
tthread::lock_guard<tthread::mutex> guard(dispatch.writeLock);
combine();//write it back
dispatch.writeCount++;
dispatch.writeCount++;
}
dispatch.writesDone.notify_one();//tell about it to the dispatch.
}
@ -1311,7 +1311,7 @@ void lightThread::work()
void lightThread::combine()
{
for(int i=0;i<canvas.size();i++)
for(int i=0;i<canvas.size();i++)
{
rgbf& c=dispatch.lightMap[i];
c=blend(c,canvas[i]);
@ -1393,7 +1393,7 @@ void lightThread::doLight( int x,int y )
surrounds += lightUpCell( power, i, j,x+i, y+j); //and this is wall hack (so that walls look nice)
if(surrounds.dot(surrounds)>0.00001f) //if we needed to light up the suroundings, then raycast
{
plotSquare(x,y,radius,
std::bind(&lightThread::doRay,this,power,x,y,_1,_2,num_diffuse));
}
@ -1438,7 +1438,7 @@ void lightThreadDispatch::shutdown()
for(int i=0;i<threadPool.size();i++)
{
threadPool[i]->isDone=true;
}
occlusionDone.notify_all();//if stuck signal that you are done with stuff.
for(int i=0;i<threadPool.size();i++)
@ -1465,7 +1465,7 @@ void threadStub(void * arg)
void lightThreadDispatch::start(int count)
{
for(int i=0;i<count;i++)
{
{
std::unique_ptr<lightThread> nthread(new lightThread(*this));
nthread->myThread=new tthread::thread(&threadStub,nthread.get());
threadPool.push_back(std::move(nthread));

@ -53,7 +53,7 @@ private:
float intensity=(light.r+light.g+light.b)/3.0;
light_adaptation=intensity*influence+light_adaptation*(1-influence);
float delta=light_adaptation-intensity;
rgbf ret;
ret.r=light.r-delta;
ret.g=light.g-delta;
@ -65,7 +65,7 @@ private:
2. light adapted, real=dark -> darker delta>0 multiplier<1
3. dark adapted, real=light -> lighter delta<0 multiplier>1
*/
//if light_adaptation/intensity!=0 then draw
//if light_adaptation/intensity!=0 then draw
}
void colorizeTile(int x,int y)
@ -98,7 +98,7 @@ private:
{
reinitLightGrid(df::global::gps->dimy,df::global::gps->dimx);
}
public:
tthread::fast_mutex dataMutex;
std::vector<rgbf> lightGrid;
@ -106,19 +106,19 @@ public:
{
reinitLightGrid();
}
virtual void update_tile(int32_t x, int32_t y) {
virtual void update_tile(int32_t x, int32_t y) {
renderer_wrap::update_tile(x,y);
tthread::lock_guard<tthread::fast_mutex> guard(dataMutex);
colorizeTile(x,y);
};
virtual void update_all() {
virtual void update_all() {
renderer_wrap::update_all();
tthread::lock_guard<tthread::fast_mutex> guard(dataMutex);
for (int x = 0; x < df::global::gps->dimx; x++)
for (int y = 0; y < df::global::gps->dimy; y++)
colorizeTile(x,y);
};
virtual void grid_resize(int32_t w, int32_t h) {
virtual void grid_resize(int32_t w, int32_t h) {
renderer_wrap::grid_resize(w,h);
reinitLightGrid(w,h);
};
@ -150,7 +150,7 @@ public:
virtual void loadSettings()=0;
virtual void clear()=0;
virtual void setHour(float h)=0;
virtual void debug(bool enable)=0;
protected:
@ -205,7 +205,7 @@ struct buildingLightDef
};
struct itemLightDef
{
matLightDef light;
matLightDef light;
bool haul;
bool equiped;
bool onGround;
@ -276,7 +276,7 @@ class lightingEngineViewscreen:public lightingEngine
{
public:
lightingEngineViewscreen(renderer_light* target);
~lightingEngineViewscreen();
~lightingEngineViewscreen();
void reinit();
void calculate();
@ -289,14 +289,14 @@ public:
private:
void fixAdvMode(int mode);
df::coord2d worldToViewportCoord(const df::coord2d& in,const DFHack::rect2d& r,const df::coord2d& window2d) ;
void doSun(const lightSource& sky,MapExtras::MapCache& map);
void doOcupancyAndLights();
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);
@ -310,7 +310,7 @@ private:
void applyMaterial(int tileId,const matLightDef& mat,float size=1, float thickness = 1);
//try to find and apply material, if failed return false, and if def!=null then apply def.
bool applyMaterial(int tileId,int matType,int matIndex,float size=1,float thickness = 1,const matLightDef* def=NULL);
size_t inline getIndex(int x,int y)
{
return x*h+y;
@ -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;
@ -343,7 +343,7 @@ private:
float dayHour; //<0 to cycle
std::vector<rgbf> dayColors; // a gradient of colors, first to 0, last to 24
///set up sane settings if setting file does not exist.
void defaultSettings();
void defaultSettings();
static int parseMaterials(lua_State* L);
static int parseSpecial(lua_State* L);

@ -79,46 +79,46 @@ public:
{
copy_from_inner();
}
virtual void update_tile(int32_t x, int32_t y) {
virtual void update_tile(int32_t x, int32_t y) {
copy_to_inner();
parent->update_tile(x,y);
};
virtual void update_all() {
virtual void update_all() {
copy_to_inner();
parent->update_all();
};
virtual void render() {
virtual void render() {
copy_to_inner();
parent->render();
};
virtual void set_fullscreen() {
virtual void set_fullscreen() {
copy_to_inner();
parent->set_fullscreen();
copy_from_inner();
};
virtual void zoom(df::zoom_commands z) {
virtual void zoom(df::zoom_commands z) {
copy_to_inner();
parent->zoom(z);
copy_from_inner();
};
virtual void resize(int32_t w, int32_t h) {
virtual void resize(int32_t w, int32_t h) {
copy_to_inner();
parent->resize(w,h);
copy_from_inner();
};
virtual void grid_resize(int32_t w, int32_t h) {
virtual void grid_resize(int32_t w, int32_t h) {
copy_to_inner();
parent->grid_resize(w,h);
copy_from_inner();
};
virtual ~renderer_wrap() {
virtual ~renderer_wrap() {
df::global::enabler->renderer=parent;
};
virtual bool get_mouse_coords(int32_t* x, int32_t* y) {
virtual bool get_mouse_coords(int32_t* x, int32_t* y) {
return parent->get_mouse_coords(x,y);
};
virtual bool uses_opengl() {
virtual bool uses_opengl() {
return parent->uses_opengl();
};
void invalidateRect(int32_t x,int32_t y,int32_t w,int32_t h)
@ -152,7 +152,7 @@ private:
float *bg = p->bg + tile * 4 * 6;
float *tex = p->tex + tile * 2 * 6;
const float val=1/2.0;
float r=rFloat()*val - val/2;
float g=rFloat()*val - val/2;
float b=rFloat()*val - val/2;
@ -176,11 +176,11 @@ public:
renderer_trippy(renderer* parent):renderer_wrap(parent)
{
}
virtual void update_tile(int32_t x, int32_t y) {
virtual void update_tile(int32_t x, int32_t y) {
renderer_wrap::update_tile(x,y);
colorizeTile(x,y);
};
virtual void update_all() {
virtual void update_all() {
renderer_wrap::update_all();
for (int x = 0; x < df::global::gps->dimx; x++)
for (int y = 0; y < df::global::gps->dimy; y++)
@ -193,7 +193,7 @@ struct rgbf
float r,g,b;
rgbf():r(0),g(0),b(0)
{
}
rgbf(float r,float g,float b):r(r),g(g),b(b)
{
@ -295,14 +295,14 @@ public:
{
reinitLightGrid();
}
virtual void update_tile(int32_t x, int32_t y) {
virtual void update_tile(int32_t x, int32_t y) {
renderer_wrap::update_tile(x,y);
tthread::lock_guard<tthread::fast_mutex> guard(dataMutex);
colorizeTile(x,y);
//some sort of mutex or sth?
//and then map read
};
virtual void update_all() {
virtual void update_all() {
renderer_wrap::update_all();
tthread::lock_guard<tthread::fast_mutex> guard(dataMutex);
for (int x = 0; x < df::global::gps->dimx; x++)
@ -322,7 +322,7 @@ public:
renderer_wrap::zoom(z);
reinitLightGrid();
}
virtual void grid_resize(int32_t w, int32_t h) {
virtual void grid_resize(int32_t w, int32_t h) {
renderer_wrap::grid_resize(w,h);
reinitLightGrid(w,h);
};
@ -388,14 +388,14 @@ public:
{
reinitGrids();
}
virtual void update_tile(int32_t x, int32_t y) {
virtual void update_tile(int32_t x, int32_t y) {
renderer_wrap::update_tile(x,y);
tthread::lock_guard<tthread::fast_mutex> guard(dataMutex);
overwriteTile(x,y);
//some sort of mutex or sth?
//and then map read
};
virtual void update_all() {
virtual void update_all() {
renderer_wrap::update_all();
tthread::lock_guard<tthread::fast_mutex> guard(dataMutex);
for (int x = 0; x < df::global::gps->dimx; x++)
@ -405,7 +405,7 @@ public:
//and then map read
//same stuff for all of them i guess...
};
virtual void grid_resize(int32_t w, int32_t h) {
virtual void grid_resize(int32_t w, int32_t h) {
renderer_wrap::grid_resize(w,h);
reinitGrids(w,h);
};

@ -106,7 +106,7 @@ void removeOld()
}
if(current_mode!=MODE_DEFAULT)
delete enabler->renderer;
current_mode=MODE_DEFAULT;
}
void installNew(df::renderer* r,RENDERER_MODE newMode)
@ -411,7 +411,7 @@ static command_result rendermax(color_ostream &out, vector <string> & parameters
renderer_light *myRender=new renderer_light(enabler->renderer);
installNew(myRender,MODE_LIGHT);
engine=new lightingEngineViewscreen(myRender);
if (Core::getInstance().isWorldLoaded())
plugin_onstatechange(out, SC_WORLD_LOADED);
}
@ -446,7 +446,7 @@ static command_result rendermax(color_ostream &out, vector <string> & parameters
}
else
out.printerr("Light mode already enabled");
return CR_OK;
}
else if(cmd=="disable")

@ -1,225 +1,225 @@
--scroll down to the end for configuration
ret={...}
ret=ret[1]
ret.materials={}
ret.buildings={}
ret.special={}
ret.items={}
ret.creatures={}
for k,v in pairs(ret) do
_ENV[k]=v
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
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)
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
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
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])
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})
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
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})
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
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
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}
end
function colorFrom16(col16)
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
end
------------------------------------------------------------------------
---------------- Configuration Starts Here -------------------------
------------------------------------------------------------------------
is_computer_quantum=false -- will enable more costly parts in the future
--special things
special.LAVA=makeMaterialDef({0.8,0.2,0.2},{0.8,0.2,0.2},5)
special.WATER=makeMaterialDef({0.5,0.5,0.8})
special.FROZEN_LIQUID=makeMaterialDef({0.2,0.7,0.9}) -- ice
special.AMBIENT=makeMaterialDef({0.85,0.85,0.85}) --ambient fog
special.CURSOR=makeMaterialDef({1,1,1},{0.96,0.84,0.03},11, {"flicker"})
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
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
--TODO dragonfire
--materials
-- 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
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
addMaterial("INORGANIC:ADAMANTINE",{0.1,0.3,0.3},{0.1,0.3,0.3},4)
-- creature stuff
addMaterial("CREATURE:DRAGON:BLOOD",nil,{0.6,0.1,0.1},4)
addGems()
--buildings
addBuilding("Statue",{1,1,1},{0.9,0.75,0.3},8)
addBuilding("Bed",{1,1,1},{0.3,0.2,0.0},2)
addBuilding("WindowGlass",nil,nil,0,{"useMaterial"})
addBuilding("WindowGem",nil,nil,0,{"useMaterial"})
addBuilding("Door",nil,nil,0,{"useMaterial"}) -- special case, only closed door obstruct/emit light
addBuilding("Floodgate",nil,nil,0,{"useMaterial"}) -- special case, only closed door obstruct/emit light
--creatures
addCreature("ELEMENTMAN_MAGMA",{0.8,0.2,0.2},{0.8,0.2,0.2},5)
--items
addItem("GEM",nil,nil,{"useMaterial","onGround"})
addItem("ROUGH",nil,nil,{"useMaterial","onGround"})
--scroll down to the end for configuration
ret={...}
ret=ret[1]
ret.materials={}
ret.buildings={}
ret.special={}
ret.items={}
ret.creatures={}
for k,v in pairs(ret) do
_ENV[k]=v
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
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)
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
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
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])
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})
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
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})
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
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
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}
end
function colorFrom16(col16)
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
end
------------------------------------------------------------------------
---------------- Configuration Starts Here -------------------------
------------------------------------------------------------------------
is_computer_quantum=false -- will enable more costly parts in the future
--special things
special.LAVA=makeMaterialDef({0.8,0.2,0.2},{0.8,0.2,0.2},5)
special.WATER=makeMaterialDef({0.5,0.5,0.8})
special.FROZEN_LIQUID=makeMaterialDef({0.2,0.7,0.9}) -- ice
special.AMBIENT=makeMaterialDef({0.85,0.85,0.85}) --ambient fog
special.CURSOR=makeMaterialDef({1,1,1},{0.96,0.84,0.03},11, {"flicker"})
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
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
--TODO dragonfire
--materials
-- 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
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
addMaterial("INORGANIC:ADAMANTINE",{0.1,0.3,0.3},{0.1,0.3,0.3},4)
-- creature stuff
addMaterial("CREATURE:DRAGON:BLOOD",nil,{0.6,0.1,0.1},4)
addGems()
--buildings
addBuilding("Statue",{1,1,1},{0.9,0.75,0.3},8)
addBuilding("Bed",{1,1,1},{0.3,0.2,0.0},2)
addBuilding("WindowGlass",nil,nil,0,{"useMaterial"})
addBuilding("WindowGem",nil,nil,0,{"useMaterial"})
addBuilding("Door",nil,nil,0,{"useMaterial"}) -- special case, only closed door obstruct/emit light
addBuilding("Floodgate",nil,nil,0,{"useMaterial"}) -- special case, only closed door obstruct/emit light
--creatures
addCreature("ELEMENTMAN_MAGMA",{0.8,0.2,0.2},{0.8,0.2,0.2},5)
--items
addItem("GEM",nil,nil,{"useMaterial","onGround"})
addItem("ROUGH",nil,nil,{"useMaterial","onGround"})
addItem("SMALLGEM",nil,nil,{"useMaterial","onGround"})

@ -56,7 +56,7 @@ static void for_each_(vector<T> &v, Fn func)
for_each(v.begin(), v.end(), func);
}
template <class T, class V, typename Fn>
template <class T, class V, typename Fn>
static void transform_(vector<T> &src, vector<V> &dst, Fn func)
{
transform(src.begin(), src.end(), back_inserter(dst), func);
@ -299,7 +299,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
commands.push_back(
PluginCommand(
"resume", "A plugin to help display and resume suspended constructions conveniently",
resume_cmd, false,
resume_cmd, false,
"resume show\n"
" Show overlay when paused:\n"
" Yellow: Suspended construction\n"

@ -321,7 +321,7 @@ module DFHack
def building_setowner(bld, unit)
return unless bld.is_room
return if bld.owner == unit
if bld.owner
if idx = bld.owner.owned_buildings.index { |ob| ob.id == bld.id }
bld.owner.owned_buildings.delete_at(idx)

@ -58,7 +58,7 @@ module DFHack
# returns an Array of all units that are current fort citizen (dwarves, on map, not hostile)
def unit_citizens
world.units.active.find_all { |u|
world.units.active.find_all { |u|
unit_iscitizen(u)
}
end
@ -178,7 +178,7 @@ module DFHack
when :Unsure
# from df code, with removed duplicate checks already in other_category
return true if u.enemy.undead or u.flags3.ghostly or u.flags1.marauder
return true if u.enemy.undead or u.flags3.ghostly or u.flags1.marauder
return false if u.flags1.forest or u.flags1.merchant or u.flags1.diplomat or u.flags2.visitor
return true if u.flags1.tame or u.flags2.underworld
@ -282,7 +282,7 @@ module DFHack
def unit_isidler(u)
unit_isworker(u) and
# current_job includes eat/drink/sleep/pickupequip
!u.job.current_job and
!u.job.current_job and
# filter 'attend meeting'
not u.specific_refs.find { |s| s.type == :ACTIVITY } and
# filter soldiers (TODO check schedule)

@ -119,7 +119,7 @@ command_result df_seedwatch(color_ostream &out, vector<string>& parameters)
World::ReadGameMode(gm);// FIXME: check return value
// if game mode isn't fortress mode
if(gm.g_mode != game_mode::DWARF ||
if(gm.g_mode != game_mode::DWARF ||
!(gm.g_type == game_type::DWARF_MAIN || gm.g_type == game_type::DWARF_RECLAIM))
{
// just print the help
@ -310,7 +310,7 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out)
t_gamemodes gm;
World::ReadGameMode(gm);// FIXME: check return value
// if game mode isn't fortress mode
if(gm.g_mode != game_mode::DWARF ||
if(gm.g_mode != game_mode::DWARF ||
!(gm.g_type == game_type::DWARF_MAIN || gm.g_type == game_type::DWARF_RECLAIM))
{
// stop running.

@ -65,7 +65,7 @@ class LuaHelper {
public:
void cycle(color_ostream &out) {
bool found = false;
if (fast) {
// Ignore the bookkeeper; either gather or enqueue orders every cycle.
found = !bookkeeping;
@ -80,7 +80,7 @@ public:
}
}
}
if (found && !bookkeeping) {
command_method("start_bookkeeping", out);
bookkeeping = true;
@ -89,7 +89,7 @@ public:
bookkeeping = false;
}
}
void init() {
stockpile_id = -1;
initialized = false;
@ -105,96 +105,96 @@ public:
initialized = false;
return command_method("clear_caches", out);
}
return true;
}
bool command_method(const char *method, color_ostream &out) {
// Calls a lua function with no parameters.
// Suspension is required for "stockflow enable" from the command line,
// but may be overkill for other situations.
CoreSuspender suspend;
auto L = Lua::Core::State;
Lua::StackUnwinder top(L);
if (!lua_checkstack(L, 1))
return false;
if (!Lua::PushModulePublic(out, L, "plugins.stockflow", method))
return false;
if (!Lua::SafeCall(out, L, 0, 0))
return false;
return true;
}
bool stockpile_method(const char *method, building_stockpilest *sp) {
// Combines the select_order and toggle_trigger method calls,
// because they share the same signature.
CoreSuspendClaimer suspend;
auto L = Lua::Core::State;
color_ostream_proxy out(Core::getInstance().getConsole());
Lua::StackUnwinder top(L);
if (!lua_checkstack(L, 2))
return false;
if (!Lua::PushModulePublic(out, L, "plugins.stockflow", method))
return false;
Lua::Push(L, sp);
if (!Lua::SafeCall(out, L, 1, 0))
return false;
// Invalidate the string cache.
stockpile_id = -1;
return true;
}
bool collect_settings(building_stockpilest *sp) {
// Find strings representing the job to order, and the trigger condition.
// There might be a memory leak here; C++ is odd like that.
auto L = Lua::Core::State;
color_ostream_proxy out(Core::getInstance().getConsole());
CoreSuspendClaimer suspend;
Lua::StackUnwinder top(L);
if (!lua_checkstack(L, 2))
return false;
if (!Lua::PushModulePublic(out, L, "plugins.stockflow", "stockpile_settings"))
return false;
Lua::Push(L, sp);
if (!Lua::SafeCall(out, L, 1, 2))
return false;
if (!lua_isstring(L, -1))
return false;
current_trigger = lua_tostring(L, -1);
lua_pop(L, 1);
if (!lua_isstring(L, -1))
return false;
current_job = lua_tostring(L, -1);
lua_pop(L, 1);
stockpile_id = sp->id;
return true;
}
void draw(building_stockpilest *sp) {
if (sp->id != stockpile_id) {
if (!collect_settings(sp)) {
@ -202,12 +202,12 @@ public:
return;
}
}
auto dims = Gui::getDwarfmodeViewDims();
int left_margin = dims.menu_x1 + 1;
int x = left_margin;
int y = dims.y2 - 3;
int links = 0;
links += sp->links.give_to_pile.size();
links += sp->links.take_from_pile.size();
@ -215,7 +215,7 @@ public:
links += sp->links.take_from_workshop.size();
if (links + 12 >= y)
y += 1;
OutputHotkeyString(x, y, current_job, "j", true, left_margin, COLOR_WHITE, COLOR_LIGHTRED);
if (*current_trigger)
OutputHotkeyString(x, y, current_trigger, " J", true, left_margin, COLOR_WHITE, COLOR_LIGHTRED);
@ -235,9 +235,9 @@ static LuaHelper helper;
#define DELTA_TICKS 600
DFhackCExport command_result plugin_onupdate(color_ostream &out) {
if (!enabled)
if (!enabled)
return CR_OK;
if (!Maps::IsValid())
return CR_OK;
@ -262,39 +262,39 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out) {
*/
struct stockflow_hook : public df::viewscreen_dwarfmodest {
typedef df::viewscreen_dwarfmodest interpose_base;
bool handleInput(set<df::interface_key> *input) {
building_stockpilest *sp = get_selected_stockpile();
if (!sp)
return false;
if (input->count(interface_key::CUSTOM_J)) {
// Select a new order for this stockpile.
if (!helper.stockpile_method("select_order", sp)) {
Core::printerr("Stockflow order selection failed!\n");
}
return true;
} else if (input->count(interface_key::CUSTOM_SHIFT_J)) {
// Toggle the order trigger for this stockpile.
if (!helper.stockpile_method("toggle_trigger", sp)) {
Core::printerr("Stockflow trigger toggle failed!\n");
}
return true;
}
return false;
}
DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input)) {
if (!handleInput(input))
INTERPOSE_NEXT(feed)(input);
}
DEFINE_VMETHOD_INTERPOSE(void, render, ()) {
INTERPOSE_NEXT(render)();
building_stockpilest *sp = get_selected_stockpile();
if (sp)
helper.draw(sp);
@ -310,17 +310,17 @@ static bool apply_hooks(color_ostream &out, bool enabling) {
out.printerr("Stockflow needs graphics.\n");
return false;
}
if (!INTERPOSE_HOOK(stockflow_hook, feed).apply(enabling) || !INTERPOSE_HOOK(stockflow_hook, render).apply(enabling)) {
out.printerr("Could not %s stockflow hooks!\n", enabling? "insert": "remove");
return false;
}
if (!helper.reset(out, enabling && Maps::IsValid())) {
out.printerr("Could not reset stockflow world data!\n");
return false;
}
return true;
}
@ -344,12 +344,12 @@ static command_result stockflow_cmd(color_ostream &out, vector <string> & parame
out.printerr("Stockflow is not currently enabled.\n");
return CR_FAILURE;
}
if (!Maps::IsValid()) {
out.printerr("You haven't loaded a map yet.\n");
return CR_FAILURE;
}
// Tell Lua to list any saved stockpile orders.
return helper.command_method("list_orders", out)? CR_OK: CR_FAILURE;
} else if (parameters[0] != "status") {
@ -358,13 +358,13 @@ static command_result stockflow_cmd(color_ostream &out, vector <string> & parame
} else if (parameters.size() > 1) {
return CR_WRONG_USAGE;
}
if (desired != enabled) {
if (!apply_hooks(out, desired)) {
return CR_FAILURE;
}
}
out.print("Stockflow is %s %s%s.\n", (desired == enabled)? "currently": "now", desired? "enabled": "disabled", fast? ", in fast mode": "");
enabled = desired;
return CR_OK;
@ -383,7 +383,7 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan
return CR_FAILURE;
}
}
return CR_OK;
}
@ -394,10 +394,10 @@ DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) {
if (!apply_hooks(out, enable)) {
return CR_FAILURE;
}
enabled = enable;
}
return CR_OK;
}
@ -407,10 +407,10 @@ DFhackCExport command_result plugin_init(color_ostream &out, std::vector <Plugin
if (!apply_hooks(out, true)) {
return CR_FAILURE;
}
enabled = true;
}
commands.push_back(PluginCommand(name, tagline, stockflow_cmd, false, usage));
return CR_OK;
}

Some files were not shown because too many files have changed in this diff Show More