Merge remote-tracking branch 'PeridexisErrant/needs_porting-cleanup'

Conflicts:
	NEWS
develop
lethosor 2015-01-05 16:21:24 -05:00
commit ad6b19f1b2
15 changed files with 213 additions and 3580 deletions

@ -1,11 +1,17 @@
DFHack Future
Internals
Fixes
plugins/dwarfmonitor: correct date display (month index, separator)
scripts/putontable: added to the readme
New Plugins
New Scripts
gui/stockpiles: an in-game interface for saving and loading stockpile
settings files.
position: Reports the current date, time, month, and season, plus
some location info. Port/update of position.py
hfs-pit: Digs a hole to hell under the cursor. Replaces needs_porting/hellhole.cpp
Misc Improvements
further work on needs_porting
DFHack 0.40.19-r1
Internals:

@ -2344,6 +2344,20 @@ For example, to grow 40 plump helmet spawn::
growcrops plump 40
hfs-pit
=======
Creates a pit to the underworld at the cursor.
Takes three arguments: diameter of the pit in tiles, whether to wall off
the pit, and whether to insert stairs. If no arguments are given, the default
is "hfs-pit 1 0 0", ie single-tile wide with no walls or stairs.
hfs-pit 4 0 1
hfs-pit 2 1 0
First example is a four-across pit with stairs but no walls; second is a
two-across pit with stairs but no walls.
lever
=====
Allow manipulation of in-game levers from the dfhack console.
@ -2414,6 +2428,16 @@ Example::
multicmd locate-ore iron ; digv
position
========
Reports the current time: date, clock time, month, and season. Also reports
location: z-level, cursor position, window size, and mouse location.
putontable
==========
Makes item appear on the table, like in adventure mode shops. Arguments: '-a'
or '--all' for all items.
quicksave
=========

@ -1,543 +0,0 @@
#ifndef SEGMENTED_FINDER_H
#define SEGMENTED_FINDER_H
#include <malloc.h>
#include <iosfwd>
#include <iterator>
class SegmentedFinder;
class SegmentFinder
{
public:
SegmentFinder(DFHack::t_memrange & mr, DFHack::Context * DF, SegmentedFinder * SF)
{
_DF = DF;
mr_ = mr;
valid=false;
if(mr.valid)
{
mr_.buffer = (uint8_t *)malloc (mr_.end - mr_.start);
_SF = SF;
try
{
DF->ReadRaw(mr_.start,(mr_.end - mr_.start),mr_.buffer);
valid = true;
}
catch (DFHack::Error::MemoryAccessDenied &)
{
free(mr_.buffer);
valid = false;
mr.valid = false; // mark the range passed in as bad
cout << "Range 0x" << hex << mr_.start << " - 0x" << mr_.end;
if (strlen(mr_.name) != 0)
cout << " (" << mr_.name << ")";
cout << dec << " not readable." << endl;
cout << "Skipping this range on future scans." << endl;
}
}
}
~SegmentFinder()
{
if(valid)
free(mr_.buffer);
}
bool isValid()
{
return valid;
}
template <class needleType, class hayType, typename comparator >
bool Find (needleType needle, const uint8_t increment , vector <uint64_t> &newfound, comparator oper)
{
if(!valid) return !newfound.empty();
//loop
for(uint64_t offset = 0; offset < (mr_.end - mr_.start) - sizeof(hayType); offset += increment)
{
if( oper(_SF,(hayType *)(mr_.buffer + offset), needle) )
newfound.push_back(mr_.start + offset);
}
return !newfound.empty();
}
template < class needleType, class hayType, typename comparator >
uint64_t FindInRange (needleType needle, comparator oper, uint64_t start, uint64_t length)
{
if(!valid) return 0;
uint64_t stopper = min((mr_.end - mr_.start) - sizeof(hayType), (start - mr_.start) - sizeof(hayType) + length);
//loop
for(uint64_t offset = start - mr_.start; offset < stopper; offset +=1)
{
if( oper(_SF,(hayType *)(mr_.buffer + offset), needle) )
return mr_.start + offset;
}
return 0;
}
template <class needleType, class hayType, typename comparator >
bool Filter (needleType needle, vector <uint64_t> &found, vector <uint64_t> &newfound, comparator oper)
{
if(!valid) return !newfound.empty();
for( uint64_t i = 0; i < found.size(); i++)
{
if(mr_.isInRange(found[i]))
{
uint64_t corrected = found[i] - mr_.start;
if( oper(_SF,(hayType *)(mr_.buffer + corrected), needle) )
newfound.push_back(found[i]);
}
}
return !newfound.empty();
}
private:
friend class SegmentedFinder;
SegmentedFinder * _SF;
DFHack::Context * _DF;
DFHack::t_memrange mr_;
bool valid;
};
class SegmentedFinder
{
public:
SegmentedFinder(vector <DFHack::t_memrange>& ranges, DFHack::Context * DF)
{
_DF = DF;
for(size_t i = 0; i < ranges.size(); i++)
{
segments.push_back(new SegmentFinder(ranges[i], DF, this));
}
}
~SegmentedFinder()
{
for(size_t i = 0; i < segments.size(); i++)
{
delete segments[i];
}
}
SegmentFinder * getSegmentForAddress (uint64_t addr)
{
for(size_t i = 0; i < segments.size(); i++)
{
if(segments[i]->mr_.isInRange(addr))
{
return segments[i];
}
}
return 0;
}
template <class needleType, class hayType, typename comparator >
bool Find (const needleType needle, const uint8_t increment, vector <uint64_t> &found, comparator oper)
{
found.clear();
for(size_t i = 0; i < segments.size(); i++)
{
segments[i]->Find<needleType,hayType,comparator>(needle, increment, found, oper);
}
return !(found.empty());
}
template < class needleType, class hayType, typename comparator >
uint64_t FindInRange (needleType needle, comparator oper, uint64_t start, uint64_t length)
{
SegmentFinder * sf = getSegmentForAddress(start);
if(sf)
{
return sf->FindInRange<needleType,hayType,comparator>(needle, oper, start, length);
}
return 0;
}
template <class needleType, class hayType, typename comparator >
bool Filter (const needleType needle, vector <uint64_t> &found, comparator oper)
{
vector <uint64_t> newfound;
for(size_t i = 0; i < segments.size(); i++)
{
segments[i]->Filter<needleType,hayType,comparator>(needle, found, newfound, oper);
}
found.clear();
found = newfound;
return !(found.empty());
}
template <class needleType, class hayType, typename comparator >
bool Incremental (needleType needle, const uint8_t increment ,vector <uint64_t> &found, comparator oper)
{
if(found.empty())
{
return Find <needleType, hayType, comparator>(needle,increment,found,oper);
}
else
{
return Filter <needleType, hayType, comparator>(needle,found,oper);
}
}
template <typename T>
T * Translate(uint64_t address)
{
for(size_t i = 0; i < segments.size(); i++)
{
if(segments[i]->mr_.isInRange(address))
{
return (T *) (segments[i]->mr_.buffer + address - segments[i]->mr_.start);
}
}
return 0;
}
template <typename T>
T Read(uint64_t address)
{
return *Translate<T>(address);
}
template <typename T>
bool Read(uint64_t address, T& target)
{
T * test = Translate<T>(address);
if(test)
{
target = *test;
return true;
}
return false;
}
private:
DFHack::Context * _DF;
vector <SegmentFinder *> segments;
};
template <typename T>
bool equalityP (SegmentedFinder* s, T *x, T y)
{
return (*x) == y;
}
struct vecTriplet
{
uint32_t start;
uint32_t finish;
uint32_t alloc_finish;
};
template <typename Needle>
bool vectorLength (SegmentedFinder* s, vecTriplet *x, Needle &y)
{
if(x->start <= x->finish && x->finish <= x->alloc_finish)
if((x->finish - x->start) == y)
return true;
return false;
}
// find a vector of 32bit pointers, where an object pointed to has a string 'y' as the first member
bool vectorString (SegmentedFinder* s, vecTriplet *x, const char *y)
{
uint32_t object_ptr;
// iterate over vector of pointers
for(uint32_t idx = x->start; idx < x->finish; idx += sizeof(uint32_t))
{
// deref ptr idx, get ptr to object
if(!s->Read(idx,object_ptr))
{
return false;
}
// deref ptr to first object, get ptr to string
uint32_t string_ptr;
if(!s->Read(object_ptr,string_ptr))
return false;
// get string location in our local cache
char * str = s->Translate<char>(string_ptr);
if(!str)
return false;
if(strcmp(y, str) == 0)
return true;
}
return false;
}
// find a vector of 32bit pointers, where the first object pointed to has a string 'y' as the first member
bool vectorStringFirst (SegmentedFinder* s, vecTriplet *x, const char *y)
{
uint32_t object_ptr;
uint32_t idx = x->start;
// deref ptr idx, get ptr to object
if(!s->Read(idx,object_ptr))
{
return false;
}
// deref ptr to first object, get ptr to string
uint32_t string_ptr;
if(!s->Read(object_ptr,string_ptr))
return false;
// get string location in our local cache
char * str = s->Translate<char>(string_ptr);
if(!str)
return false;
if(strcmp(y, str) == 0)
return true;
return false;
}
// test if the address is between vector.start and vector.finish
// not very useful alone, but could be a good step to filter some things
bool vectorAddrWithin (SegmentedFinder* s, vecTriplet *x, uint32_t address)
{
if(address < x->finish && address >= x->start)
return true;
return false;
}
// test if an object address is within the vector of pointers
//
bool vectorOfPtrWithin (SegmentedFinder* s, vecTriplet *x, uint32_t address)
{
uint32_t object_ptr;
for(uint32_t idx = x->start; idx < x->finish; idx += sizeof(uint32_t))
{
if(!s->Read(idx,object_ptr))
{
return false;
}
if(object_ptr == address)
return true;
}
return false;
}
bool vectorAll (SegmentedFinder* s, vecTriplet *x, int )
{
if(x->start <= x->finish && x->finish <= x->alloc_finish)
{
if(s->getSegmentForAddress(x->start) == s->getSegmentForAddress(x->finish)
&& s->getSegmentForAddress(x->finish) == s->getSegmentForAddress(x->alloc_finish))
return true;
}
return false;
}
class Bytestreamdata
{
public:
void * object;
uint32_t length;
uint32_t allocated;
uint32_t n_used;
};
class Bytestream
{
public:
Bytestream(void * obj, uint32_t len, bool alloc = false)
{
d = new Bytestreamdata();
d->allocated = alloc;
d->object = obj;
d->length = len;
d->n_used = 1;
constant = false;
}
Bytestream()
{
d = new Bytestreamdata();
d->allocated = false;
d->object = 0;
d->length = 0;
d->n_used = 1;
constant = false;
}
Bytestream( Bytestream & bs)
{
d =bs.d;
d->n_used++;
constant = false;
}
Bytestream( const Bytestream & bs)
{
d =bs.d;
d->n_used++;
constant = true;
}
~Bytestream()
{
d->n_used --;
if(d->allocated && d->object && d->n_used == 0)
{
free (d->object);
free (d);
}
}
bool Allocate(size_t bytes)
{
if(constant)
return false;
if(d->allocated)
{
d->object = realloc(d->object, bytes);
}
else
{
d->object = malloc( bytes );
}
if(d->object)
{
d->allocated = bytes;
return true;
}
else
{
d->allocated = 0;
return false;
}
}
template < class T >
bool insert( T what )
{
if(constant)
return false;
if(d->length+sizeof(T) >= d->allocated)
Allocate((d->length+sizeof(T)) * 2);
(*(T *)( (uint64_t)d->object + d->length)) = what;
d->length += sizeof(T);
return true;
}
Bytestreamdata * d;
bool constant;
};
std::ostream& operator<< ( std::ostream& out, Bytestream& bs )
{
if(bs.d->object)
{
out << "bytestream " << dec << bs.d->length << "/" << bs.d->allocated << " bytes" << endl;
for(size_t i = 0; i < bs.d->length; i++)
{
out << hex << (int) ((uint8_t *) bs.d->object)[i] << " ";
}
out << endl;
}
else
{
out << "empty bytestresm" << endl;
}
return out;
}
std::istream& operator>> ( std::istream& out, Bytestream& bs )
{
string read;
while(!out.eof())
{
string tmp;
out >> tmp;
read.append(tmp);
}
cout << read << endl;
bs.d->length = 0;
size_t first = read.find_first_of("\"");
size_t last = read.find_last_of("\"");
size_t start = first + 1;
if(first == read.npos)
{
std::transform(read.begin(), read.end(), read.begin(), (int(*)(int)) tolower);
bs.Allocate(read.size()); // overkill. size / 2 should be good, but this is safe
int state = 0;
char big = 0;
char small = 0;
string::iterator it = read.begin();
// iterate through string, construct a bytestream out of 00-FF bytes
while(it != read.end())
{
char reads = *it;
if((reads >='0' && reads <= '9'))
{
if(state == 0)
{
big = reads - '0';
state = 1;
}
else if(state == 1)
{
small = reads - '0';
state = 0;
bs.insert<char>(big*16 + small);
}
}
if((reads >= 'a' && reads <= 'f'))
{
if(state == 0)
{
big = reads - 'a' + 10;
state = 1;
}
else if(state == 1)
{
small = reads - 'a' + 10;
state = 0;
bs.insert<char>(big*16 + small);
}
}
it++;
}
// we end in state= 1. should we add or should we trim... or throw errors?
// I decided on adding
if (state == 1)
{
small = 0;
bs.insert<char>(big*16 + small);
}
}
else
{
if(last == first)
{
// only one "
last = read.size();
}
size_t length = last - start;
// construct bytestream out of stuff between ""
bs.d->length = length;
if(length)
{
// todo: Bytestream should be able to handle this without external code
bs.Allocate(length);
bs.d->length = length;
const char* strstart = read.c_str();
memcpy(bs.d->object, strstart + start, length);
}
else
{
bs.d->object = 0;
}
}
cout << bs;
return out;
}
bool findBytestream (SegmentedFinder* s, void *addr, Bytestream compare )
{
if(memcmp(addr, compare.d->object, compare.d->length) == 0)
return true;
return false;
}
bool findString (SegmentedFinder* s, uint32_t *addr, const char * compare )
{
// read string pointer, translate to local scheme
char *str = s->Translate<char>(*addr);
// verify
if(!str)
return false;
if(strcmp(str, compare) == 0)
return true;
return false;
}
bool findStrBuffer (SegmentedFinder* s, uint32_t *addr, const char * compare )
{
if(memcmp((const char *)addr, compare, strlen(compare)) == 0)
return true;
return false;
}
#endif // SEGMENTED_FINDER_H

@ -1,30 +1,9 @@
Notes by PeridexisErrant, on the needs_porting scripts and plugins:
I deleted:
attachtest.py obsolete
digger.cpp less useful than digger2, replaced by autochop
digger2.cpp replaced by digfort
dfstatus.cpp replaced by dfstatus.lua
drawtile.cpp replaced by tiletypes
fix-3708.cpp obsolete, bug fixed in vanilla
lair.cpp replaced by lair
reveal.py replaced by reveal
treedump.py replaced by prospect & autochop
veinlook.cpp replaced by prospect
veinswap.cpp replaced by changevein
To investigate further:
creaturemanager.cpp modify skills and labors of creatures, kill creatures, etc; impressive but I suspect most functions implemented elsewhere
digpattern.cpp allows multi-Z designations. Obsolete, or is there more here?
incrementalsearch.cpp linux-only memory stuff; unqualified to judge
SegementedFinder.h more memory stuff
To port:
copypaste.cpp high value target - a proof of concept plugin to allow copy-pasting in DF; does both terrain and buildings/constructions
dfbauxtite.cpp changes material of mechanisms to bauxtite (ie magma-safe)
hellhole.cpp instantly creates a hole to the HFS
hotkeynotedump.py outputs a list of hotkeys and names; most useful before keybindings were possible. Trival to port but low value.
itemdesignator.cpp mostly replaced by Falconne's enhanced stocks, but could port the interesting 'set fire to things' function
position.py outputs very detailed time& place info
TODO:
copypaste.cpp
high value target - a proof of concept plugin to allow copy-pasting in DF; does both terrain and buildings/constructions
creaturemanager.cpp
modify skills and labors of creatures, kill creatures, etc; impressive but I suspect most functions implemented elsewhere
In progress:
hotkey-notes.lua
prints list of hotkeys with name and jump position

@ -1,161 +0,0 @@
/*
DFBauxite - Converts all your mechanisms to bauxite (for use in magma).
Author: Alex Legg
Based on code from and uses DFHack - www.sourceforge.net/projects/dfhack
*/
#include <sstream>
#include <iostream>
#include <string.h>
#include <cstdlib>
#include <assert.h>
#include <string>
#include <vector>
using namespace std;
#include <DFIntegers.h>
#include <DFExport.h>
#include <DFError.h>
#include <DFVector.h>
#include <DFMemInfo.h>
#include <DFProcess.h>
#include <DFTypes.h>
using namespace DFHack;
int main ()
{
DFHack::Process *proc;
DFHack::memory_info *meminfo;
DFHack::DfVector <uint32_t> *items_vector;
DFHack::t_item_df40d item_40d;
DFHack::t_matglossPair item_40d_material;
vector<DFHack::t_matgloss> stoneMat;
uint32_t item_material_offset;
uint32_t temp;
int32_t type;
int items;
int found = 0, converted = 0;
DFHack::ContextManager DF("Memory.xml");
try
{
DF.Attach();
}
catch (exception& e)
{
cerr << e.what() << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
return 1;
}
// Find out which material is bauxite
if(!DF.ReadStoneMatgloss(stoneMat))
{
cout << "Materials not supported for this version of DF, exiting." << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
DF.Detach();
return EXIT_FAILURE;
}
int bauxiteIndex = -1;
for (int i = 0; i < stoneMat.size();i++)
{
if(strcmp(stoneMat[i].id, "BAUXITE") == 0)
{
bauxiteIndex = i;
break;
}
}
if(bauxiteIndex == -1)
{
cout << "Cannot locate bauxite in the DF raws, exiting" << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
DF.Detach();
return EXIT_FAILURE;
}
// Get some basics needed for full access
proc = DF.getProcess();
meminfo = proc->getDescriptor();
// Get the object name/ID mapping
//FIXME: work on the 'supported features' system required
// Check availability of required addresses and offsets (doing custom stuff here)
items = meminfo->getAddress("items");
item_material_offset = meminfo->getOffset("item_materials");
if( !items || ! item_material_offset)
{
cout << "Items not supported for this DF version, exiting" << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
DF.Detach();
return EXIT_FAILURE;
}
items_vector = new DFHack::DfVector <uint32_t> (proc, items);
for(uint32_t i = 0; i < items_vector->size(); i++)
{
// get pointer to object
temp = items_vector->at (i);
// read object
proc->read (temp, sizeof (DFHack::t_item_df40d), (uint8_t *) &item_40d);
// resolve object type
type = -1;
// skip things we can't identify
if(!meminfo->resolveObjectToClassID (temp, type))
continue;
string classname;
if(!meminfo->resolveClassIDToClassname (type, classname))
continue;
if(classname == "item_trapparts")
{
proc->read (temp + item_material_offset, sizeof (DFHack::t_matglossPair), (uint8_t *) &item_40d_material);
cout << dec << "Mechanism at x:" << item_40d.x << " y:" << item_40d.y << " z:" << item_40d.z << " ID:" << item_40d.ID << endl;
if (item_40d_material.index != bauxiteIndex)
{
item_40d_material.index = bauxiteIndex;
proc->write (temp + item_material_offset, sizeof (DFHack::t_matglossPair), (uint8_t *) &item_40d_material);
converted++;
}
found++;
}
}
if (found == 0)
{
cout << "No mechanisms to convert" << endl;
} else {
cout << found << " mechanisms found" << endl;
cout << converted << " mechanisms converted" << endl;
}
DF.Resume();
DF.Detach();
delete items_vector;
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();
#endif
return 0;
}

@ -1,259 +0,0 @@
#include <iostream>
#include <string.h> // for memset
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <stdio.h>
#include <cstdlib>
using namespace std;
#include <DFHack.h>
#include <extra/MapExtras.h>
using namespace MapExtras;
//#include <argstream.h>
void usage(int argc, const char * argv[])
{
cout
<< "Usage:" << endl
<< argv[0] << " [option 1] [option 2] [...]" << endl
<< "-q : Suppress \"Press any key to continue\" at program termination" << endl
<< "-u <n> : Dig upwards <n> times (default 5)" << endl
<< "-d <n> : Dig downwards <n> times (default 5)" << endl
;
}
void digat(MapCache * MCache, DFHack::DFCoord xy)
{
int16_t tt;
tt = MCache->tiletypeAt(xy);
if(!DFHack::isWallTerrain(tt))
return;
// found a good tile, dig+unset material
DFHack::t_designation des = MCache->designationAt(xy);
if(MCache->testCoord(xy))
{
MCache->clearMaterialAt(xy);
if(des.bits.dig == DFHack::designation_no)
des.bits.dig = DFHack::designation_default;
MCache->setDesignationAt(xy,des);
}
}
int strtoint(const string &str)
{
stringstream ss(str);
int result;
return ss >> result ? result : -1;
}
typedef struct
{
int16_t x;
int16_t y;
} pos;
int main (int argc, const char* argv[])
{
// Command line options
bool updown = false;
bool quiet = true;
// let's be more useful when double-clicked on windows
#ifndef LINUX_BUILD
quiet = false;
#endif
int dig_up_n = 5;
int dig_down_n = 5;
for(int i = 1; i < argc; i++)
{
string arg_cur = argv[i];
string arg_next = "";
int arg_next_int = -99999;
/* Check if argv[i+1] is a number >= 0 */
if (i < argc-1) {
arg_next = argv[i+1];
arg_next_int = strtoint(arg_next);
if (arg_next != "0" && arg_next_int == 0) {
arg_next_int = -99999;
}
}
if (arg_cur == "-x")
{
updown = true;
}
else if (arg_cur == "-q")
{
quiet = true;
}
else if(arg_cur == "-u" && i < argc-1)
{
if (arg_next_int < 0 || arg_next_int >= 99999) {
usage(argc, argv);
return 1;
}
dig_up_n = arg_next_int;
i++;
}
else if(arg_cur == "-d" && i < argc-1)
{
if (arg_next_int < 0 || arg_next_int >= 99999) {
usage(argc, argv);
return 1;
}
dig_down_n = arg_next_int;
i++;
}
else
{
usage(argc, argv);
return 1;
}
}
DFHack::ContextManager DFMgr("Memory.xml");
DFHack::Context * DF;
try
{
DF = DFMgr.getSingleContext();
DF->Attach();
}
catch (exception& e)
{
cerr << "Error getting context: " << e.what() << endl;
if (!quiet)
cin.ignore();
return 1;
}
uint32_t x_max,y_max,z_max;
DFHack::Maps * Maps = DF->getMaps();
DFHack::Gui * Gui = DF->getGui();
// init the map
if(!Maps->Start())
{
cerr << "Can't init map. Make sure you have a map loaded in DF." << endl;
DF->Detach();
if (!quiet)
cin.ignore();
return 1;
}
int32_t cx, cy, cz;
Maps->getSize(x_max,y_max,z_max);
uint32_t tx_max = x_max * 16;
uint32_t ty_max = y_max * 16;
Gui->getCursorCoords(cx,cy,cz);
if (cx == -30000)
{
cerr << "Cursor is not active. Point the cursor at the position to dig at." << endl;
DF->Detach();
if (!quiet)
{
cin.ignore();
}
return 1;
}
DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz);
if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1)
{
cerr << "I won't dig the borders. That would be cheating!" << endl;
DF->Detach();
if (!quiet)
{
cin.ignore();
}
return 1;
}
MapCache * MCache = new MapCache(Maps);
DFHack::t_designation des = MCache->designationAt(xy);
int16_t tt = MCache->tiletypeAt(xy);
int16_t veinmat = MCache->veinMaterialAt(xy);
/*
if( veinmat == -1 )
{
cerr << "This tile is non-vein. Bye :)" << endl;
delete MCache;
DF->Detach();
if (!quiet) {
cin.ignore();
}
return 1;
}
*/
printf("Digging at (%d/%d/%d), tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole);
// 1 < xy.x < tx_max - 1
// 1 < xy.y < ty_max - 1
// xy.z
// X____
// X_XXX
// XXXXX
// __XXX
// __XXX
// _____
pos map[] =
{
{ 0,0 }
, { 0,1 }
, { 0,2 } , { 2,2 }, { 3,2 }, { 4,2 }
, { 0,3 }, { 1,3 }, { 2,3 }, { 3,3 }, { 4,3 }
, { 2,4 }, { 3,4 }, { 4,4 }
// this is mirrored, goes left instead of right
, {-2,2 }, {-3,2 }, {-4,2 }
, {-1,3 }, {-2,3 }, {-3,3 }, {-4,3 }
, {-2,4 }, {-3,4 }, {-4,4 }
};
DFHack::DFCoord npos = xy;
if (dig_up_n > 0)
{
for (int j = 0; j < dig_up_n; j++)
{
for (int i = 0; i < sizeof(map)/sizeof(map[0]); i++)
{
npos=xy;
npos.x += map[i].x;
npos.y -= 4*j + map[i].y;
printf("Digging at (%d/%d/%d)\n", npos.x, npos.y, npos.z);
digat(MCache, npos);
}
}
}
if (dig_down_n > 0)
{
for (int j = 0; j < dig_down_n; j++)
{
for (int i = 0; i < sizeof(map)/sizeof(map[0]); i++)
{
npos=xy;
npos.x += map[i].x;
npos.y += 4*j + map[i].y;
printf("Digging at (%d/%d/%d)\n", npos.x, npos.y, npos.z);
digat(MCache, npos);
}
}
}
MCache->WriteAll();
delete MCache;
DF->Detach();
if (!quiet) {
cout << "Done. Press any key to continue" << endl;
cin.ignore();
}
return 0;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,40 @@
-- prints info on assigned hotkeys to the console
local hotkeys = {'F1 ', 'F2 ', 'F3 ', 'F4 ', 'F5 ', 'F6 ',
'F7 ', 'F8 ', 'F9 ', 'F10', 'F11', 'F12'}
for i=1, #hotkeys do
local hk = hotkeys[i]
hk = {id=hk}
-- PLACEHOLDER PROPERTIES ONLY!
hk.name = '_name'
hk.x = df.global.window_x
hk.y = df.global.window_y
hk.z = df.global.window_z
print(hk.id..' '..hk.name..' X= '..hk.x..', Y= '..hk.y..', Z= '..hk.z)
end
--[[
# the (very) old Python version...
from context import Context, ContextManager
cm = ContextManager("Memory.xml")
df = cm.get_single_context()
df.attach()
gui = df.gui
print "Hotkeys"
hotkeys = gui.read_hotkeys()
for key in hotkeys:
print "x: %d\ny: %d\tz: %d\ttext: %s" % (key.x, key.y, key.z, key.name)
df.detach()
print "Done. Press any key to continue"
raw_input()
]]--

@ -1,20 +0,0 @@
from context import Context, ContextManager
cm = ContextManager("Memory.xml")
df = cm.get_single_context()
df.attach()
gui = df.gui
print "Hotkeys"
hotkeys = gui.read_hotkeys()
for key in hotkeys:
print "x: %d\ny: %d\tz: %d\ttext: %s" % (key.x, key.y, key.z, key.name)
df.detach()
print "Done. Press any key to continue"
raw_input()

File diff suppressed because it is too large Load Diff

@ -1,148 +0,0 @@
// Item designator
#include <iostream>
#include <iomanip>
#include <sstream>
#include <climits>
#include <vector>
using namespace std;
#include <DFHack.h>
#include <DFVector.h>
using namespace DFHack;
int main ()
{
DFHack::ContextManager CM ("Memory.xml");
DFHack::Context * DF;
DFHack::VersionInfo *mem;
DFHack::Gui * Gui;
DFHack::Materials * Mats;
DFHack::Items * Items;
cout << "This utility lets you mass-designate items by type and material." << endl
<< "Like set on fire all MICROCLINE item_stone..." << endl
<< "Some unusual combinations might be untested and cause the program to crash..."<< endl
<< "so, watch your step and backup your fort" << endl;
try
{
DF = CM.getSingleContext();
DF->Attach();
mem = DF->getMemoryInfo();
Gui = DF->getGui();
Mats = DF->getMaterials();
Mats->ReadAllMaterials();
Items = DF->getItems();
}
catch (exception& e)
{
cerr << e.what() << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
return 1;
}
DFHack::Process * p = DF->getProcess();
DFHack::OffsetGroup* itemGroup = mem->getGroup("Items");
unsigned vector_addr = itemGroup->getAddress("items_vector");
DFHack::DfVector <uint32_t> p_items (p, vector_addr);
uint32_t numItems = p_items.size();
map< string, map<string,vector< dfh_item > > > itemmap;
map< string, map< string, vector< dfh_item > > >::iterator it1;
int failedItems = 0;
map <string, int > bad_mat_items;
for(uint32_t i=0; i< numItems; i++)
{
DFHack::dfh_item temp;
Items->readItem(p_items[i],temp);
string typestr = Items->getItemClass(temp);
string material = Mats->getDescription(temp.matdesc);
itemmap[typestr][material].push_back(temp);
}
int i =0;
for( it1 = itemmap.begin(); it1!=itemmap.end();it1++)
{
cout << i << ": " << it1->first << "\n";
i++;
}
if(i == 0)
{
cout << "No items found" << endl;
DF->Detach();
return 0;
}
cout << endl << "Select an item type from the list:";
int number;
string in;
stringstream ss;
getline(cin, in);
ss.str(in);
ss >> number;
int j = 0;
it1 = itemmap.begin();
while(j < number && it1!=itemmap.end())
{
it1++;
j++;
}
cout << it1->first << "\n";
map<string,vector<dfh_item> >::iterator it2;
i=0;
for(it2 = it1->second.begin();it2!=it1->second.end();it2++){
cout << i << ":\t" << it2->first << " [" << it2->second.size() << "]" << endl;
i++;
}
cout << endl << "Select a material type: ";
int number2;
ss.clear();
getline(cin, in);
ss.str(in);
ss >> number2;
decideAgain:
cout << "Select a designation - (d)ump, (f)orbid, (m)melt, set on fi(r)e :" << flush;
string designationType;
getline(cin,designationType);
DFHack::t_itemflags changeFlag = {0};
if(designationType == "d" || designationType == "dump")
{
changeFlag.dump = 1;
}
else if(designationType == "f" || designationType == "forbid")
{
changeFlag.forbid = 1;
}
else if(designationType == "m" || designationType == "melt")
{
changeFlag.melt = 1;
}
else if(designationType == "r" || designationType == "fire")
{
changeFlag.on_fire = 1;
}
else
{
goto decideAgain;
}
j=0;
it2= it1->second.begin();
while(j < number2 && it2!=it1->second.end())
{
it2++;
j++;
}
for(uint32_t k = 0;k< it2->second.size();k++)
{
DFHack::dfh_item & t = it2->second[k];
t.base.flags.whole |= changeFlag.whole;
Items->writeItem(t);
}
DF->Detach();
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();
#endif
return 0;
}

@ -1,71 +0,0 @@
import sys
from pydfhack import ContextManager
df_cm = ContextManager("Memory.xml")
df = df_cm.get_single_context()
if not df.attach():
print "Unable to attach!"
print "Press any key to continue"
raw_input()
sys.exit(1)
gui = df.gui
if gui is not None:
maps = df.maps
world = df.world
have_maps = maps.start()
world.start()
gm = world.read_game_mode()
if gm is not None:
print gm
date_tuple = (world.read_current_year(), world.read_current_month(), world.read_current_day(), world.read_current_tick())
print "Year: %d Month: %d Day: %d Tick: %d" % date_tuple
v_coords = gui.get_view_coords()
c_coords = gui.get_cursor_coords()
w_coords = (-1, -1, -1)
world_pos_string = ""
if have_maps is True:
w_coords = maps.getPosition()
x = (v_coords[0] + w_coords[0]) * 48
y = (v_coords[1] + w_coords[1]) * 48
z = (v_coords[2] + w_coords[2])
world_pos_string = " world: %d/%d/%d" % (x, y, z)
print "Map world offset: %d/%d/%d embark squares" % w_coords
if v_coords != (-1, -1, -1):
print "view coords: %d/%d/%d" % v_coords
if have_maps is True:
print world_pos_string
if c_coords != (-1, -1, -1):
print "cursor coords: %d/%d/%d" % c_coords
if have_maps is True:
print world_pos_string
window_size = gui.get_window_size()
if window_size != (-1, -1):
print "window size : %d %d" % window_size
else:
print "cursor and window parameters are unsupported on your version of DF"
if not df.detach():
print "Unable to detach!"
print "Done. Press any key to continue"
raw_input()

@ -1722,10 +1722,10 @@ struct dwarf_monitor_hook : public df::viewscreen_dwarfmodest
int y = 0;
ostringstream date_str;
auto month = World::ReadCurrentMonth();
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());

@ -0,0 +1,88 @@
-- Creates a pit under the target leading straight to the Underworld. Type '?' for help.
-- Based on script by IndigoFenix, @ https://gist.github.com/IndigoFenix/8776696
args={...}
if args[1] == '?' then
print("Example usage: 'hfs-pit 2 1 1'")
print("First parameter is size of the pit in all directions.")
print("Second parameter is 1 to wall off the sides of the pit on all layers except the underworld, or anything else to leave them open.")
print("Third parameter is 1 to add stairs. Stairs are buggy; they will not reveal the bottom until you dig somewhere, but underworld creatures will path in.")
print("If no arguments are given, the default is 'hfs-pit 1 0 0', ie single-tile wide with no walls or stairs.")
return
end
pos = copyall(df.global.cursor)
size = tonumber(args[1])
if size == nil or size < 1 then size = 1 end
wallOff = tonumber(args[2])
stairs = tonumber(args[3])
--Get the layer of the underworld
for index,value in ipairs(df.global.world.cur_savegame.map_features) do
local featureType=value:getType()
if featureType==9 then --Underworld
underworldLayer = value.layer
end
end
if pos.x==-30000 then
qerror("Select a location by placing the cursor")
end
local x = 0
local y = 0
for x=pos.x-size,pos.x+size,1 do
for y=pos.y-size,pos.y+size,1 do
z=1
local hitAir = false
local hitCeiling = false
while z <= pos.z do
local block = dfhack.maps.ensureTileBlock(x,y,z)
if block then
if block.tiletype[x%16][y%16] ~= 335 then
hitAir = true
end
if hitAir == true then
if not hitCeiling then
if block.global_feature ~= underworldLayer or z > 10 then hitCeiling = true end
if stairs == 1 and x == pos.x and y == pos.y then
if block.tiletype[x%16][y%16] == 32 then
if z == pos.z then
block.tiletype[x%16][y%16] = 56
else
block.tiletype[x%16][y%16] = 55
end
else
block.tiletype[x%16][y%16] = 57
end
end
end
if hitCeiling == true then
if block.designation[x%16][y%16].flow_size > 0 or wallOff == 1 then needsWall = true else needsWall = false end
if (x == pos.x-size or x == pos.x+size or y == pos.y-size or y == pos.y+size) and z==pos.z then
--Do nothing, this is the lip of the hole
elseif x == pos.x-size and y == pos.y-size then if needsWall == true then block.tiletype[x%16][y%16]=320 end
elseif x == pos.x-size and y == pos.y+size then if needsWall == true then block.tiletype[x%16][y%16]=321 end
elseif x == pos.x+size and y == pos.y+size then if needsWall == true then block.tiletype[x%16][y%16]=322 end
elseif x == pos.x+size and y == pos.y-size then if needsWall == true then block.tiletype[x%16][y%16]=323 end
elseif x == pos.x-size or x == pos.x+size then if needsWall == true then block.tiletype[x%16][y%16]=324 end
elseif y == pos.y-size or y == pos.y+size then if needsWall == true then block.tiletype[x%16][y%16]=325 end
elseif stairs == 1 and x == pos.x and y == pos.y then
if z == pos.z then block.tiletype[x%16][y%16]=56
else block.tiletype[x%16][y%16]=55 end
else block.tiletype[x%16][y%16]=32
end
block.designation[x%16][y%16].hidden = false
--block.designation[x%16][y%16].liquid_type = true -- if true, magma. if false, water.
block.designation[x%16][y%16].flow_size = 0
dfhack.maps.enableBlockUpdates(block)
block.designation[x%16][y%16].flow_forbid = false
end
end
block.designation[x%16][y%16].hidden = false
end
z = z+1
end
end
end

@ -0,0 +1,43 @@
--prints current time and position
local months = {
'Granite, in early Spring.',
'Slate, in mid Spring.',
'Felsite, in late Spring.',
'Hematite, in early Summer.',
'Malachite, in mid Summer.',
'Galena, in late Summer.',
'Limestone, in early Autumn.',
'Sandstone, in mid Autumn.',
'Timber, in late Autumn.',
'Moonstone, in early Winter.',
'Opal, in mid Winter.',
'Obsidian, in late Winter.',
}
--Fortress mode counts 1200 ticks per day and 403200 per year
--Adventurer mode counts 86400 ticks to a day and 29030400 ticks per year
--Twelve months per year, 28 days to every month, 336 days per year
local julian_day = math.floor(df.global.cur_year_tick / 1200) + 1
local month = math.floor(julian_day / 28) + 1 --days and months are 1-indexed
local day = julian_day % 28
local time_of_day = math.floor(df.global.cur_year_tick_advmode / 336)
local second = time_of_day % 60
local minute = math.floor(time_of_day / 60) % 60
local hour = math.floor(time_of_day / 3600) % 24
print('Time:')
print(' The time is '..string.format('%02d:%02d:%02d', hour, minute, second))
print(' The date is '..string.format('%05d-%02d-%02d', df.global.cur_year, month, day))
print(' It is the month of '..months[month])
--TODO: print(' It is the Age of '..age_name)
print('Place:')
print(' The z-level is z='..df.global.window_z)
print(' The cursor is at x='..df.global.cursor.x..', y='..df.global.cursor.y)
print(' The window is '..df.global.gps.dimx..' tiles wide and '..df.global.gps.dimy..' tiles high')
if df.global.gps.mouse_x == -1 then print(' The mouse is not in the DF window') else
print(' The mouse is at x='..df.global.gps.mouse_x..', y='..df.global.gps.mouse_y..' within the window') end
--TODO: print(' The fortress is at '..x, y..' on the world map ('..worldsize..' square)')