Merge remote-tracking branch 'PeridexisErrant/needs_porting-cleanup'
Conflicts: NEWSdevelop
commit
ad6b19f1b2
@ -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:
|
TODO:
|
||||||
|
copypaste.cpp
|
||||||
I deleted:
|
high value target - a proof of concept plugin to allow copy-pasting in DF; does both terrain and buildings/constructions
|
||||||
attachtest.py obsolete
|
creaturemanager.cpp
|
||||||
digger.cpp less useful than digger2, replaced by autochop
|
modify skills and labors of creatures, kill creatures, etc; impressive but I suspect most functions implemented elsewhere
|
||||||
digger2.cpp replaced by digfort
|
|
||||||
dfstatus.cpp replaced by dfstatus.lua
|
In progress:
|
||||||
drawtile.cpp replaced by tiletypes
|
hotkey-notes.lua
|
||||||
fix-3708.cpp obsolete, bug fixed in vanilla
|
prints list of hotkeys with name and jump position
|
||||||
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
|
|
||||||
|
@ -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()
|
|
@ -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)')
|
Loading…
Reference in New Issue