Petr Mrázek 2011-12-30 03:12:29 +01:00
commit e6ff6b04fc
24 changed files with 1008 additions and 644 deletions

@ -598,7 +598,48 @@ void OffsetGroup::setInvalid(INVAL_TYPE invalidity)
(*iter4).second->setInvalid(invalidity);
}
}
std::vector<OffsetKey> OffsetGroup::getKeys() const
{
std::vector<OffsetKey> ret;
OffsetKey K;
K.keytype=IS_ADDRESS;
for(uint32_Iter iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
{
K.key=iter->first;
K.inval=iter->second.first;
ret.push_back(K);
}
K.keytype=IS_OFFSET;
for(int32_Iter iter = OGd->offsets.begin(); iter != OGd->offsets.end(); iter++)
{
K.key=iter->first;
K.inval=iter->second.first;
ret.push_back(K);
}
K.keytype=IS_HEX_VAL;
for(uint32_Iter iter = OGd->hexvals.begin(); iter != OGd->hexvals.end(); iter++)
{
K.key=iter->first;
K.inval=iter->second.first;
ret.push_back(K);
}
K.keytype=IS_STRING;
for(strings_Iter iter = OGd->strings.begin(); iter != OGd->strings.end(); iter++)
{
K.key=iter->first;
K.inval=iter->second.first;
ret.push_back(K);
}
K.keytype=IS_GROUP;
K.inval=IS_VALID;
for(groups_Iter iter = OGd->groups.begin(); iter != OGd->groups.end(); iter++)
{
K.key=iter->first;
ret.push_back(K);
}
return ret;
}
/*
* Private data
*/

@ -52,7 +52,20 @@ namespace DFHack
IS_INVALID,
IS_VALID
};
enum KEY_TYPE
{
IS_OFFSET,
IS_ADDRESS,
IS_HEX_VAL,
IS_STRING,
IS_GROUP
};
struct OffsetKey
{
std::string key;
INVAL_TYPE inval;
KEY_TYPE keytype;
};
/*
* Offset Group
*/
@ -96,6 +109,8 @@ namespace DFHack
std::string getFullName();
OffsetGroup * getParent();
void setInvalid(INVAL_TYPE arg1);
std::vector<OffsetKey> getKeys() const;
};
/*

@ -7,6 +7,9 @@ set(
${dfhack_SOURCE_DIR}/library/depends/tthread/tinythread.cpp
${DFUSION_CPPS}
)
DFHACK_PLUGIN(dfusion ${DFUSION_CPPS_ALL} LINK_LIBRARIES lua)
FILE(GLOB DFUSION_HS include/*)
SET_SOURCE_FILES_PROPERTIES( ${DFUSION_HS} PROPERTIES HEADER_FILE_ONLY TRUE )
DFHACK_PLUGIN(dfusion ${DFUSION_CPPS_ALL} ${DFUSION_HS} LINK_LIBRARIES lua)
# installs into DF root
install(DIRECTORY luafiles/ DESTINATION dfusion)

@ -18,6 +18,7 @@
#include "lua_Misc.h"
#include "lua_VersionInfo.h"
#include "functioncall.h"
#include "lua_FunctionCall.h"
using std::vector;
using std::string;
@ -45,6 +46,8 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
lua::RegisterHexsearch(st);
lua::RegisterMisc(st);
lua::RegisterVersionInfo(st);
lua::RegisterFunctionCall(st);
#ifdef LINUX_BUILD
st.push(1);
st.setglobal("LINUX");
@ -53,7 +56,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
st.setglobal("WINDOWS");
#endif
commands.push_back(PluginCommand("dfusion","Init dfusion system. Use 'dfusion thready' to spawn a different thread.",dfusion));
commands.push_back(PluginCommand("dfusion","Init dfusion system. Use 'dfusion init' to run dfusion in init mode (not interactive).",dfusion));
commands.push_back(PluginCommand("lua", "Run interactive interpreter. Use 'lua <filename>' to run <filename> instead.",lua_run));
mymutex=new tthread::mutex;
@ -171,13 +174,18 @@ void RunDfusion(void *p)
}
DFhackCExport command_result dfusion (Core * c, vector <string> & parameters)
{
if(thread_dfusion==0)
thread_dfusion=new tthread::thread(RunDfusion,c);
if(parameters[0]!="thready")
if(parameters[0]=="init")
{
thread_dfusion->join();
delete thread_dfusion;
thread_dfusion=0;
lua::state s=lua::glua::Get();
s.push(1);
s.setglobal("INIT");
}
else
{
lua::state s=lua::glua::Get();
s.push();
s.setglobal("INIT");
}
RunDfusion(c);
return CR_OK;
}

@ -0,0 +1,14 @@
#ifndef LUA_FUNCTIONCALL__H
#define LUA_FUNCTIONCALL__H
#include "luamain.h"
#include "functioncall.h"
namespace lua
{
void RegisterFunctionCall(lua::state &st);
}
#endif

@ -28,6 +28,7 @@ public:
int getName(lua_State *L);
int getFullName(lua_State *L);
int getParent(lua_State *L);
int getKeys(lua_State *L);
DEF_LUNE(OffsetGroup);
};

@ -3,6 +3,11 @@ STD_STRING=0
DWORD=1
WORD=2
BYTE=3
function printd(...)
if DEBUG then
print(...)
end
end
function GetTextRegion()
if __TEXT ~=nil then --Chache this, not going to change.
return __TEXT
@ -324,7 +329,7 @@ function findVectors()
local loc1,loc2
loc1=engine.peekd(v+2)
loc2=engine.peekd(v+8)
print(string.format("%x - %x=%x",loc1,loc2,loc1-loc2))
--print(string.format("%x - %x=%x",loc1,loc2,loc1-loc2))
if(loc1-loc2==4) then
if T[loc1-4]~=nil then
T[loc1-4]=T[loc1-4]+1

@ -0,0 +1,71 @@
function MakeTable(modpos,modsize,names)
count=0
castes={}
--print("Making table")
for _,line in pairs(names) do
--print("Line:"..line)
tpos=string.find(line,":")
if tpos~=nil then
--print("Was line:"..line)
table.insert(castes,tonumber(string.sub(line,tpos+1)))
line=string.sub(line,1,tpos-1)
--print("IS line:"..line)
else
table.insert(castes,-1)
end
if RaceTable[line] == nil then
error("Failure, "..line.." not found!")
end
engine.pokew(modpos+modsize+count*2,RaceTable[line]) -- add race
count = count + 1
end
i=0
for _,caste in pairs(castes) do
engine.pokew(modpos+modsize+count*2+i*2,caste) -- add caste
i= i+1
end
engine.poked(stoff,count)
return count
end
function embark(names)
RaceTable=RaceTable or BuildNameTable()
mypos=engine.getmod('Embark')
stoff=offsets.getEx('StartDwarfs')
if mypos then --if mod already loaded
print("Mod already loaded @:"..mypos.." just updating")
modpos=mypos
_,modsize=engine.loadobj('dfusion/embark/embark.o')
count=MakeTable(modpos,modsize,names) --just remake tables
else
tofind=VersionInfo.getGroup("Creatures"):getAddress("current_race")--offsets.getEx('CurrentRace')
loc=offsets.find(stoff,0xa1,DWORD_,tofind)
print("found:"..loc)
if((loc~=0)and(loc-stoff<1000)) then
modpos,modsize=engine.loadmod('dfusion/embark/embark.o','Embark',256)
count=MakeTable(modpos,modsize,names)
engine.poked(modpos+0x18,modpos+modsize) --fix array start for race
engine.poked(modpos+0x08,modpos+modsize+count*2) --fix array start for caste
print("sucess loading mod @:"..modpos)
-- build race vector after module.
--finaly poke in the call!
engine.pokeb(loc,0x6a)
engine.pokeb(loc+1,0xFF)
engine.pokeb(loc+2,0xe8)
engine.poked(loc+3,modpos-loc-7)
--engine.pokeb(loc+5,0x90)
SetExecute(modpos)
else
error("did not find patch location, failing...")
end
end
end

@ -1,74 +1,4 @@
function MakeTable(modpos,modsize,names)
count=0
castes={}
--print("Making table")
for _,line in pairs(names) do
--print("Line:"..line)
tpos=string.find(line,":")
if tpos~=nil then
--print("Was line:"..line)
table.insert(castes,tonumber(string.sub(line,tpos+1)))
line=string.sub(line,1,tpos-1)
--print("IS line:"..line)
else
table.insert(castes,-1)
end
if RaceTable[line] == nil then
error("Failure, "..line.." not found!")
end
engine.pokew(modpos+modsize+count*2,RaceTable[line]) -- add race
count = count + 1
end
i=0
for _,caste in pairs(castes) do
engine.pokew(modpos+modsize+count*2+i*2,caste) -- add caste
i= i+1
end
engine.poked(stoff,count)
return count
end
function embark(names)
RaceTable=RaceTable or BuildNameTable()
mypos=engine.getmod('Embark')
stoff=offsets.getEx('StartDwarfs')
if mypos then --if mod already loaded
print("Mod already loaded @:"..mypos.." just updating")
modpos=mypos
_,modsize=engine.loadobj('dfusion/embark/embark.o')
count=MakeTable(modpos,modsize,names) --just remake tables
else
tofind=VersionInfo.getGroup("Creatures"):getAddress("current_race")--offsets.getEx('CurrentRace')
loc=offsets.find(stoff,0xa1,DWORD_,tofind)
print("found:"..loc)
if((loc~=0)and(loc-stoff<1000)) then
modpos,modsize=engine.loadmod('dfusion/embark/embark.o','Embark',256)
count=MakeTable(modpos,modsize,names)
engine.poked(modpos+0x18,modpos+modsize) --fix array start for race
engine.poked(modpos+0x08,modpos+modsize+count*2) --fix array start for caste
print("sucess loading mod @:"..modpos)
-- build race vector after module.
--finaly poke in the call!
engine.pokeb(loc,0x6a)
engine.pokeb(loc+1,0xFF)
engine.pokeb(loc+2,0xe8)
engine.poked(loc+3,modpos-loc-7)
--engine.pokeb(loc+5,0x90)
SetExecute(modpos)
else
error("did not find patch location, failing...")
end
end
end
if not(FILE)then
names=ParseNames("dfusion/embark/races.txt")--io.open("plugins/embark/races.txt"):lines()
embark(names)

@ -0,0 +1 @@
as -anl --32 -o friendship_c.o friendship_c.asm

@ -0,0 +1,41 @@
.intel_syntax
eaxpart:
push eax
push ecx
jmp compare
ecxpart:
push eax
push ecx
mov eax,ecx
compare:
push ebx
mov ebx,0xDEADBEEF #write a pointer to the list of allowed civs
mov ecx,2000 #write a number of allowed civs
loop1:
cmp [ebx+ecx*4],eax
jnz endok
dec ecx
cmp ecx ,-1
jnz loop1
pop ebx
jmp fail
endok:
pop ebx
cmp eax,eax
jmp endfinal
fail:
xor ecx,ecx
xor eax,eax
inc eax
cmp eax,ebx
endfinal:
pop ecx
pop eax
ret

@ -0,0 +1,89 @@
friendship_civ={}
function friendship_civ.init()
friendship_civ.count=0x0f
friendship_civ.firsttime=true
local mypos=engine.getmod("Friendship_civ")
local modpos=0
if mypos then
modpos=mypos
_,modsize=engine.loadobj("dfusion/friendship_civ/friendship_c.o")
_=nil
friendship_civ.firsttime=false
else
modpos,modsize=engine.loadmod("dfusion/friendship_civ/friendship_c.o","Friendship_civ",1024)
print(string.format("Loaded module @:%x",modpos))
end
friendship_civ.modpos=modpos
friendship_civ.modsize=modsize
end
function friendship_civ.install(civs)
friendship_civ.init()
local count=0
for _,v in pairs(civs) do
engine.poked(friendship_civ.modpos+friendship_civ.modsize+count*4,v) -- for some reason it compiled strangely
-- cmp word[ebx+ecx*2],ax -> cmp word[ebx+ecx*2+2],ax
count = count + 1
end
engine.poked(friendship_civ.modpos+0x0a,friendship_civ.modpos+friendship_civ.modsize) -- set ptr to civ ids
engine.poked(friendship_civ.modpos+friendship_civ.count,count-1) -- set count of civs
SetExecute(friendship_civ.modpos)
if(friendship_civ.firsttime) then
friendship_civ.patch()
end
end
function friendship_civ.getcivs()
if(friendship_civ.firsttime==nil)then
return nil
end
friendship_civ.init()
local count=engine.peekd(friendship_civ.modpos+friendship_civ.count)+1
local ret={}
for i=0, count-1 do
table.insert(ret,engine.peekd(friendship_civ.modpos+friendship_civ.modsize+i*4))
end
return ret
end
function friendship_civ.addciv(civ) --if called with nil add current civ :)
if civ==nil then
local cciv=engine.peekd(VersionInfo.getGroup("Creatures"):getAddress("current_civ"))
friendship_civ.install({cciv})
return
end
local oldcivs=friendship_civ.getcivs()
oldcivs=oldcivs or {}
if type(civ)=="table" then
for k,v in ipairs(civ) do
table.insert(oldcivs,v)
end
else
table.insert(oldcivs,civ)
end
friendship_civ.install(oldcivs)
end
function friendship_civ.patch_call(off,iseax)
local calltrg=friendship_civ.modpos
if not iseax then
calltrg=calltrg+4
end
engine.pokeb(off,0xe8) --this is a call
engine.poked(off+1,calltrg-off-5) --offset to call to (relative)
engine.pokeb(off+5,0x90) --nop
end
function friendship_civ.patch()
--UpdateRanges()
local civloc= VersionInfo.getGroup("Creatures"):getAddress("current_civ")
local pos1=offsets.findall(0,0x3B,0x05,DWORD_,civloc) --eax
for k,v in pairs(pos1) do print(string.format("%d %x",k,v)) end
local pos2=offsets.findall(0,0x3B,0x0D,DWORD_,civloc) --ecx
for k,v in pairs(pos2) do print(string.format("%d %x",k,v)) end
for k,v in pairs(pos1) do
print(string.format("Patching eax compare %d: %x",k,v))
friendship_civ.patch_call(v,true)
end
for k,v in pairs(pos2) do
print(string.format("Patching ecx compare %d: %x",k,v))
friendship_civ.patch_call(v,false)
end
end

@ -0,0 +1,57 @@
fc_ui={}
fc_ui.menu=MakeMenu()
function fc_ui.get()
local mycivs=friendship_civ.getcivs()
if mycivs~= nil then
print(" Currently friendly civs:")
for k,v in pairs(mycivs) do
print(string.format("%d. %d",k,v))
end
else
print(" Plugin no yet activated.")
end
end
function fc_ui.add()
print("Type in civ id to add (leave empty to add current, q cancels):")
local r
while r==nil and r~='q' do
r=io.stdin:read()
if r=="" then
r=nil
break
end
if r~='q' then r=tonumber(r) else
return
end
end
friendship_civ.addciv(r)
end
function fc_ui.remove()
local mycivs=friendship_civ.getcivs()
if mycivs~= nil then
print(" Currently friendly civs:")
for k,v in pairs(mycivs) do
print(string.format("%d. %d",k,v))
end
else
print(" Plugin no yet activated, nothing to remove.")
return
end
print("Type in civ id to remove( q cancels):")
local r
while r==nil and r~='q' do
r=io.stdin:read()
if r~='q' then
r=tonumber(r)
if r>#mycivs then r=nil end
else
return
end
end
table.remove(mycivs,r)
friendship_civ.install(mycivs)
end
fc_ui.menu:add("Add civ",fc_ui.add)
fc_ui.menu:add("Get civs",fc_ui.get)
fc_ui.menu:add("Remove civ",fc_ui.remove)
fc_ui.menu:display()

@ -43,12 +43,14 @@ function mainmenu(t1)
end
end
dofile("dfusion/common.lua")
dofile("dfusion/utils.lua")
unlockDF()
plugins={}
table.insert(plugins,{"simple_embark","A simple embark dwarf count editor"})
table.insert(plugins,{"items","A collection of item hacking tools"})
table.insert(plugins,{"offsets","Find all offsets"})
table.insert(plugins,{"friendship","Multi race fort enabler"})
table.insert(plugins,{"friendship_civ","Multi civ fort enabler"})
table.insert(plugins,{"embark","Multi race embark"})
table.insert(plugins,{"adv_tools","some tools for (mainly) advneturer hacking"})
table.insert(plugins,{"tools","some misc tools"})
@ -56,6 +58,14 @@ table.insert(plugins,{"triggers","a function calling plug (discontinued...)"})
table.insert(plugins,{"migrants","multi race imigrations"})
table.insert(plugins,{"onfunction","run lua on some df function"})
loadall(plugins)
dofile_silent("dfusion/initcustom.lua")
print("Locating saves...")
local str=engine.peekstr(0x1447A40+offsets.base())
print("Current region:"..str)
str="data/save/"..str.."/dfusion/init.lua"
dofile_silent(str)
if not INIT then
mainmenu(plugins)
end

@ -0,0 +1,61 @@
--install part
function migrants(names)
RaceTable=RaceTable or BuildNameTable()
mypos=engine.getmod("Migrants")
if mypos then
print("Migrant mod is running already @:"..mypos)
modpos=mypos
_,modsize=engine.loadobj("dfusion/migrants/migrants.o")
count=0
for _,v in pairs(names) do
if RaceTable[v] == nil then
print("Failure, "..v.." not found!")
break --maybe some indication of failure? and cleanup?
end
engine.pokew(modpos+modsize+count*2+4,RaceTable[v])
count = count + 1
end
seedpos=modpos+modsize
engine.poked(seedpos,math.random(1234567)) -- seed the generator :)
engine.poked(modpos+0x1c,count) --max size for div
else
modpos,modsize=engine.loadmod("dfusion/migrants/migrants.o","Migrants")
print(string.format("Loaded module @:%x",modpos))
count=0
for _,v in pairs(names) do
if RaceTable[v] == nil then
print("Failure, "..v.." not found!")
break --maybe some indication of failure? and cleanup?
end
engine.pokew(modpos+modsize+count*2+4,RaceTable[v])
count = count + 1
end
seedpos=modpos+modsize
engine.poked(modpos+0x04,seedpos)
engine.poked(modpos+0x15,seedpos)
engine.poked(seedpos,math.random(1234567)) -- seed the generator :)
engine.poked(modpos+0x1c,count) --max size for div
engine.poked(modpos+0x26,seedpos+4) --start of array
--patch part
--pos=62873C+DF
-- pattern: A1,DWORD_,"CURRENTRACE",56,89,ANYBYTE,ANYBYTE,34,e8
pos=offsets.find(offsets.base(),0xa1,DWORD_,offsets.getEx("CurrentRace"),0x56,0x89,ANYBYTE,ANYBYTE,0x34,0xe8)
function pokeCall(off)
engine.pokeb(off,0xe8)
engine.poked(off+1,modpos-off-5)
end
if pos~=0 then
print(string.format("Found @:%x",pos))
pokeCall(pos)
else
print("Not found patch location!!!")
end
end
end

@ -1,64 +1,4 @@
--install part
function migrants(names)
RaceTable=RaceTable or BuildNameTable()
mypos=engine.getmod("Migrants")
if mypos then
print("Migrant mod is running already @:"..mypos)
modpos=mypos
_,modsize=engine.loadobj("dfusion/migrants/migrants.o")
count=0
for _,v in pairs(names) do
if RaceTable[v] == nil then
print("Failure, "..v.." not found!")
break --maybe some indication of failure? and cleanup?
end
engine.pokew(modpos+modsize+count*2+4,RaceTable[v])
count = count + 1
end
seedpos=modpos+modsize
engine.poked(seedpos,math.random(1234567)) -- seed the generator :)
engine.poked(modpos+0x1c,count) --max size for div
else
modpos,modsize=engine.loadmod("dfusion/migrants/migrants.o","Migrants")
print(string.format("Loaded module @:%x",modpos))
count=0
for _,v in pairs(names) do
if RaceTable[v] == nil then
print("Failure, "..v.." not found!")
break --maybe some indication of failure? and cleanup?
end
engine.pokew(modpos+modsize+count*2+4,RaceTable[v])
count = count + 1
end
seedpos=modpos+modsize
engine.poked(modpos+0x04,seedpos)
engine.poked(modpos+0x15,seedpos)
engine.poked(seedpos,math.random(1234567)) -- seed the generator :)
engine.poked(modpos+0x1c,count) --max size for div
engine.poked(modpos+0x26,seedpos+4) --start of array
--patch part
--pos=62873C+DF
-- pattern: A1,DWORD_,"CURRENTRACE",56,89,ANYBYTE,ANYBYTE,34,e8
pos=offsets.find(offsets.base(),0xa1,DWORD_,offsets.getEx("CurrentRace"),0x56,0x89,ANYBYTE,ANYBYTE,0x34,0xe8)
function pokeCall(off)
engine.pokeb(off,0xe8)
engine.poked(off+1,modpos-off-5)
end
if pos~=0 then
print(string.format("Found @:%x",pos))
pokeCall(pos)
else
print("Not found patch location!!!")
end
end
end
if not(FILE) then
names=ParseNames("dfusion/migrants/races.txt")--io.open("plugins/migrants/races.txt"):lines()
migrants(names)

@ -7,6 +7,7 @@ if WINDOWS then --windows function defintions
onfunction.AddFunction(0x3d4301+offsets.base(),"Make_Item",{item_type="esp"})
onfunction.AddFunction(0x5af826+offsets.base(),"Hurt",{target="esi",attacker={off=0x74,rtype=DWORD,reg="esp"}})
onfunction.AddFunction(0x3D5886+offsets.base(),"Flip",{building="esi"})
onfunction.AddFunction(0x35E340+offsets.base(),"ItemCreate")
else --linux
onfunction.AddFunction(0x899befe+offsets.base(),"Move") -- found out by attaching watch...
onfunction.AddFunction(0x850eecd+offsets.base(),"Die",{creature="ebx"}) -- same

@ -195,7 +195,7 @@ ptr_CrGloss.castes={off=296,rtype=ptr_vector}
ptr_CrCaste={}
ptr_CrCaste.name={off=0,rtype=ptt_dfstring}
ptr_CrCaste.flags_ptr={off=0x524,rtype=DWORD} --size 17?
ptr_CrCaste.flags_ptr={off=0x5A0,rtype=DWORD} --size 17?
--[=[
Flags:
57 - is sentient (allows setting labours)

@ -0,0 +1,497 @@
tools={}
tools.menu=MakeMenu()
function tools.setrace()
RaceTable=RaceTable or BuildNameTable() --slow.If loaded don't load again
print("Your current race is:"..GetRaceToken(engine.peekw(offsets.getEx('CurrentRace'))))
print("Type new race's token name in full caps:")
repeat
entry=io.stdin:read()
id=RaceTable[entry]
until id~=nil
engine.pokew(offsets.getEx('CurrentRace'),id)
end
tools.menu:add("Set current race",tools.setrace)
function tools.GiveSentience(names) --TODO make pattern...
RaceTable=RaceTable or BuildNameTable() --slow.If loaded don't load again
if names ==nil then
ids={}
print("Type race's token name in full caps to give sentience to:")
repeat
entry=io.stdin:read()
id=RaceTable[entry]
until id~=nil
table.insert(ids,id)
else
ids={}
for _,name in pairs(names) do
id=RaceTable[name]
table.insert(ids,id)
end
end
for _,id in pairs(ids) do
local off=offsets.getEx('CreatureGloss')
local races=engine.peek(off,ptr_vector)
--print("Vector start:"..off)
off=races:getval(id)
print(string.format("race location:%x",off))
local castes=engine.peek(off,ptr_CrGloss.castes)
print(string.format("Caste count:%i",castes:size()))
local flagPattern=ptt_dfflag.new(17)
for i =0,castes:size()-1 do
local offCaste=castes:getval(i)
print("Caste name:"..engine.peek(offCaste,ptr_CrCaste.name):getval().."...")
local flagoffset=engine.peek(offCaste,ptr_CrCaste.flags_ptr)
local flags=engine.peek(flagoffset,flagPattern)
--print(string.format("%x",flagoffset))
if flags:get(57) then
print("\tis sentient.")
else
print("\tnon sentient. Allocating IQ...")
flags:set(57,1)
engine.poke(flagoffset,flagPattern,flags)
end
end
end
end
tools.menu:add("Give Sentience",tools.GiveSentience)
function tools.embark()
off=offsets.find(0,0x66, 0x83, 0x7F ,0x1A ,0xFF,0x74,0x04)
if off~=0 then
engine.pokeb(off+5,0x90)
engine.pokeb(off+6,0x90)
print("Found and patched")
else
print("not found")
end
end
tools.menu:add("Embark anywhere",tools.embark)
function tools.getlegendsid(croff)
local vec=engine.peek(croff,ptr_Creature.legends)
if vec:size()==0 then
return 0
end
for i =0,vector:size()-1 do
--if engine.peekd(vec:getval(i))~=0 then
-- print(string.format("%x",engine.peekd(vec:getval(i))-offsets.base()))
--end
if(engine.peekd(vec:getval(i))==offsets.getEx("vtableLegends")) then --easy to get.. just copy from player's-base
return engine.peekd(vec:getval(i)+4)
end
end
return 0
end
function tools.getCreatureId(vector)
tnames={}
rnames={}
--[[print("vector1 size:"..vector:size())
print("vector2 size:"..vector2:size())]]--
for i=0,vector:size()-1 do
--print(string.format("%x",vector:getval(i)))
local name=engine.peek(vector:getval(i),ptt_dfstring):getval()
local lid= tools.getlegendsid(vector:getval(i))
if lid ~=0 then
print(i..")*Creature Name:"..name.." race="..engine.peekw(vector:getval(i)+ptr_Creature.race.off).." legendid="..lid)
else
print(i..") Creature Name:"..name.." race="..engine.peekw(vector:getval(i)+ptr_Creature.race.off))
end
if name ~="" and name~=nil then
tnames[i]=name
rnames[name]=i
end
end
print("=====================================")
print("type in name or number:")
r=io.stdin:read()
if tonumber(r) ==nil then
indx=rnames[r]
if indx==nil then return end
else
r=tonumber(r)
if r<vector:size() then indx=r else return end
end
return indx
end
function tools.change_adv()
myoff=offsets.getEx("AdvCreatureVec")
vector=engine.peek(myoff,ptr_vector)
indx=tools.getCreatureId(vector)
print("Swaping, press enter when done or 'q' to stay, 's' to stay with legends id change")
tval=vector:getval(0)
vector:setval(0,vector:getval(indx))
vector:setval(indx,tval)
r=io.stdin:read()
if r=='q' then
return
end
if r~='s' then
tval=vector:getval(0)
vector:setval(0,vector:getval(indx))
vector:setval(indx,tval)
end
local lid=tools.getlegendsid(vector:getval(0))
if lid~=0 then
engine.poked(offsets.getEx("PlayerLegend"),lid)
else
print("Warning target does not have a valid legends id!")
end
end
tools.menu:add("Change Adventurer",tools.change_adv)
function tools.MakeFollow()
myoff=offsets.getEx("AdvCreatureVec")
vector=engine.peek(myoff,ptr_vector)
indx=tools.getCreatureId(vector)
print(string.format("current creature:%x",vector:getval(indx)))
trgid=engine.peek(vector:getval(0)+ptr_Creature.ID.off,DWORD)
lfollow=engine.peek(vector:getval(indx)+ptr_Creature.followID.off,DWORD)
if lfollow ~=0xFFFFFFFF then
print("Already following, unfollow? y/N")
r=io.stdin:read()
if r== "y" then
engine.poke(vector:getval(indx)+ptr_Creature.followID.off,DWORD,0)
end
else
engine.poke(vector:getval(indx)+ptr_Creature.followID.off,DWORD,trgid)
end
end
tools.menu:add("Make creature follow",tools.MakeFollow)
function tools.runscript(files)
if files==nil then
files={}
table.insert(files,io.stdin:read())
end
for _,v in pairs(files) do
print("Running script:"..v)
ParseScript(v)
end
end
function tools.getsite(names)
if words==nil then --do once its slow.
words,rwords=BuildWordTables()
end
if names==nil then
print("Type words that are in the site name, FULLCAPS, no modifiers (lovely->LOVE), q to quit:")
names={}
repeat
w=io.stdin:read();
if rwords[w]~=nil then
table.insert(names,w)
print("--added--")
end
until w=='q'
end
tnames={}
for _,v in pairs(names) do
if rwords[v] ~=nil then
table.insert(tnames,rwords[v]) --get word numbers
end
end
local offsites=engine.peekd(offsets.getEx("SiteData"))+0x120
snames={" pfort"," dfort"," cave","mohall","forest","hamlet","imploc"," lair"," fort"," camp"}
vector=engine.peek(offsites,ptr_vector)
print("Number of sites:"..vector:size())
print("List of hits:")
for i =0,vector:size()-1 do
off=vector:getval(i)
good=true
r=""
hits=0
sname=engine.peek(off,ptr_site.name)
for k=0,6 do
vnum=sname[k]--engine.peekd(off+0x38+k*4)
tgood=false
if vnum~=0xFFFFFFFF then
--print(string.format("%x",vnum))
if names[vnum]~=nil then
r=r..names[vnum].." "
end
for _,v in pairs(tnames) do
if vnum==v then
tgood=true
--print("Match")
hits=hits+1
break
end
end
if not tgood then
good=false
end
end
end
if(good) and (hits>0)then
--if true then
--print("=====================")
typ=engine.peek(off,ptr_site.type)--engine.peekw(off+0x78)
flg=engine.peekd(engine.peek(off,ptr_site.flagptr))
--flg=engine.peekd(off+224)
--flg2=engine.peekw(off)
--tv=engine.peek(off+0x84,ptr_vector)
--tv2=engine.peek(off+0xA4,ptr_vector)
print(string.format("%d)%s off=%x type=%s\t flags=%x",i,r,off,snames[typ+1],flg))
if i%100==99 then
r=io.stdin:read()
end
end
end
print("Type which to change (q cancels):")
repeat
r=io.stdin:read()
n=tonumber(r)
if(r=='q') then return end
until n~=nil
return vector:getval(n)
end
function tools.changesite(names)
off=tools.getsite(names)
snames={"Mountain halls (yours)","Dark fort","Cave","Mountain hall (NPC)","Forest retreat","Hamlet","Important location","Lair","Fort","Camp"}
print("Type in the site type (q cancels):")
for k,v in pairs(snames) do
print((k-1).."->"..v)
end
repeat
r=io.stdin:read()
n2=tonumber(r)
if(r=='q') then return end
until n2~=nil
--off=vector:getval(n)
print(string.format("%x->%d",off,n2))
engine.poke(off,ptr_site.type,n2)
end
function tools.changeflags(names)
myflag_pattern=ptt_dfflag.new(3*8)
off=tools.getsite(names)
offflgs=engine.peek(off,ptr_site.flagptr)
q=''
print(string.format("Site offset %x flags offset %x",off,offflgs))
repeat
print("flags:")
--off=vector:getval(n)
flg=engine.peek(offflgs,myflag_pattern)
r=""
for i=0,3*8-1 do
if flg:get(i)==1 then
r=r.."x"
else
r=r.."o"
end
if i%8==7 then
print(i-7 .."->"..r)
r=""
end
end
print("Type number to flip, or 'q' to quit.")
q=io.stdin:read()
n2=tonumber(q)
if n2~=nil then
flg:flip(n2)
engine.poke(offflgs,myflag_pattern,flg)
end
until q=='q'
end
function tools.hostilate()
vector=engine.peek(offsets.getEx("CreatureVec"),ptr_vector)
id=engine.peekd(offsets.getEx("CreaturePtr"))
print(string.format("Vec:%d cr:%d",vector:size(),id))
off=vector:getval(id)
crciv=engine.peek(off,ptr_Creature.civ)
print("Creatures civ:"..crciv)
curciv=engine.peekd(offsets.getEx("CurrentRace")-12)
print("My civ:"..curciv)
if curciv==crciv then
print("Friendly-making enemy")
engine.poke(off,ptr_Creature.civ,-1)
flg=engine.peek(off,ptr_Creature.flags)
flg:set(17,0)
print("flag 51:"..tostring(flg:get(51)))
engine.poke(off,ptr_Creature.flags,flg)
else
print("Enemy- making friendly")
engine.poke(off,ptr_Creature.civ,curciv)
flg=engine.peek(off,ptr_Creature.flags)
flg:set(17,1)
flg:set(19,0)
engine.poke(off,ptr_Creature.flags,flg)
end
end
function tools.mouseBlock()
local xs,ys,zs
xs,ys,zs=getxyz()
xs=math.floor(xs/16)
ys=math.floor(ys/16)
print("Mouse block is:"..xs.." "..ys.." "..zs)
end
function tools.protectsite()
local mapoffset=offsets.getEx("WorldData")--0x131C128+offsets.base()
local x=engine.peek(mapoffset+24,DWORD)
local y=engine.peek(mapoffset+28,DWORD)
local z=engine.peek(mapoffset+32,DWORD)
--vec=engine.peek(mapoffset,ptr_vector)
print("Blocks loaded:"..x.." "..y.." "..z)
print("Select type:")
print("1. All (SLOW)")
print("2. range (x0 x1 y0 y1 z0 z1)")
print("3. One block around pointer")
print("anything else- quit")
q=io.stdin:read()
n2=tonumber(q)
if n2==nil then return end
if n2>3 or n2<1 then return end
local xs,xe,ys,ye,zs,ze
if n2==1 then
xs=0
xe=x-1
ys=0
ye=y-1
zs=0
ze=z-1
elseif n2==2 then
print("enter x0:")
xs=tonumber(io.stdin:read())
print("enter x1:")
xe=tonumber(io.stdin:read())
print("enter y0:")
ys=tonumber(io.stdin:read())
print("enter y1:")
ye=tonumber(io.stdin:read())
print("enter z0:")
zs=tonumber(io.stdin:read())
print("enter z1:")
ze=tonumber(io.stdin:read())
function clamp(t,vmin,vmax)
if t> vmax then return vmax end
if t< vmin then return vmin end
return t
end
xs=clamp(xs,0,x-1)
ys=clamp(ys,0,y-1)
zs=clamp(zs,0,z-1)
xe=clamp(xe,xs,x-1)
ye=clamp(ye,ys,y-1)
ze=clamp(ze,zs,z-1)
else
xs,ys,zs=getxyz()
xs=math.floor(xs/16)
ys=math.floor(ys/16)
xe=xs
ye=ys
ze=zs
end
local xblocks=engine.peek(mapoffset,DWORD)
local flg=bit.lshift(1,14)
for xx=xs,xe do
local yblocks=engine.peek(xblocks+xx*4,DWORD)
for yy=ys,ye do
local zblocks=engine.peek(yblocks+yy*4,DWORD)
for zz=zs,ze do
local myblock=engine.peek(zblocks+zz*4,DWORD)
if myblock~=0 then
for i=0,255 do
local ff=engine.peek(myblock+0x67c+i*4,DWORD)
ff=bit.bor(ff,flg) --set 14 flag to 1
engine.poke(myblock+0x67c+i*4,DWORD,ff)
end
end
end
print("Blocks done:"..xx.." "..yy)
end
end
end
function tools.fixwarp()
local mapoffset=offsets.getEx("WorldData")--0x131C128+offsets.base()
local x=engine.peek(mapoffset+24,DWORD)
local y=engine.peek(mapoffset+28,DWORD)
local z=engine.peek(mapoffset+32,DWORD)
--vec=engine.peek(mapoffset,ptr_vector)
print("Blocks loaded:"..x.." "..y.." "..z)
print("Select type:")
print("1. All (SLOW)")
print("2. range (x0 x1 y0 y1 z0 z1)")
print("3. One block around pointer")
print("anything else- quit")
q=io.stdin:read()
n2=tonumber(q)
if n2==nil then return end
if n2>3 or n2<1 then return end
local xs,xe,ys,ye,zs,ze
if n2==1 then
xs=0
xe=x-1
ys=0
ye=y-1
zs=0
ze=z-1
elseif n2==2 then
print("enter x0:")
xs=tonumber(io.stdin:read())
print("enter x1:")
xe=tonumber(io.stdin:read())
print("enter y0:")
ys=tonumber(io.stdin:read())
print("enter y1:")
ye=tonumber(io.stdin:read())
print("enter z0:")
zs=tonumber(io.stdin:read())
print("enter z1:")
ze=tonumber(io.stdin:read())
function clamp(t,vmin,vmax)
if t> vmax then return vmax end
if t< vmin then return vmin end
return t
end
xs=clamp(xs,0,x-1)
ys=clamp(ys,0,y-1)
zs=clamp(zs,0,z-1)
xe=clamp(xe,xs,x-1)
ye=clamp(ye,ys,y-1)
ze=clamp(ze,zs,z-1)
else
xs,ys,zs=getxyz()
xs=math.floor(xs/16)
ys=math.floor(ys/16)
xe=xs
ye=ys
ze=zs
end
local xblocks=engine.peek(mapoffset,DWORD)
local flg=bit.bnot(bit.lshift(1,3))
for xx=xs,xe do
local yblocks=engine.peek(xblocks+xx*4,DWORD)
for yy=ys,ye do
local zblocks=engine.peek(yblocks+yy*4,DWORD)
for zz=zs,ze do
local myblock=engine.peek(zblocks+zz*4,DWORD)
if myblock~=0 then
for i=0,255 do
local ff=engine.peek(myblock+0x67c+i*4,DWORD)
ff=bit.band(ff,flg) --set 14 flag to 1
engine.poke(myblock+0x67c+i*4,DWORD,ff)
end
end
end
print("Blocks done:"..xx.." "..yy)
end
end
end

@ -1,501 +1,5 @@
--local bit = require("bit")
tools={}
tools.menu=MakeMenu()
function tools.setrace()
RaceTable=RaceTable or BuildNameTable() --slow.If loaded don't load again
print("Your current race is:"..GetRaceToken(engine.peekw(offsets.getEx('CurrentRace'))))
print("Type new race's token name in full caps:")
repeat
entry=io.stdin:read()
id=RaceTable[entry]
until id~=nil
engine.pokew(offsets.getEx('CurrentRace'),id)
end
tools.menu:add("Set current race",tools.setrace)
function tools.GiveSentience(names) --TODO make pattern...
RaceTable=RaceTable or BuildNameTable() --slow.If loaded don't load again
if names ==nil then
ids={}
print("Type race's token name in full caps to give sentience to:")
repeat
entry=io.stdin:read()
id=RaceTable[entry]
until id~=nil
table.insert(ids,id)
else
ids={}
for _,name in pairs(names) do
id=RaceTable[name]
table.insert(ids,id)
end
end
for _,id in pairs(ids) do
local off=offsets.getEx('CreatureGloss')
local races=engine.peek(off,ptr_vector)
--print("Vector start:"..off)
off=races:getval(id)
print(string.format("race location:%x",off))
local castes=engine.peek(off,ptr_CrGloss.castes)
print(string.format("Caste count:%i",castes:size()))
local flagPattern=ptt_dfflag.new(17)
for i =0,castes:size()-1 do
local offCaste=castes:getval(i)
print("Caste name:"..engine.peek(offCaste,ptr_CrCaste.name):getval().."...")
local flagoffset=engine.peek(offCaste,ptr_CrCaste.flags_ptr)
local flags=engine.peek(flagoffset,flagPattern)
--print(string.format("%x",flagoffset))
if flags:get(57) then
print("\tis sentient.")
else
print("\tnon sentient. Allocating IQ...")
flags:set(57,1)
engine.poke(flagoffset,flagPattern,flags)
end
end
end
end
tools.menu:add("Give Sentience",tools.GiveSentience)
function tools.embark()
off=offsets.find(0,0x66, 0x83, 0x7F ,0x1A ,0xFF,0x74,0x04)
if off~=0 then
engine.pokeb(off+5,0x90)
engine.pokeb(off+6,0x90)
print("Found and patched")
else
print("not found")
end
end
tools.menu:add("Embark anywhere",tools.embark)
function tools.getlegendsid(croff)
local vec=engine.peek(croff,ptr_Creature.legends)
if vec:size()==0 then
return 0
end
for i =0,vector:size()-1 do
--if engine.peekd(vec:getval(i))~=0 then
-- print(string.format("%x",engine.peekd(vec:getval(i))-offsets.base()))
--end
if(engine.peekd(vec:getval(i))==offsets.getEx("vtableLegends")) then --easy to get.. just copy from player's-base
return engine.peekd(vec:getval(i)+4)
end
end
return 0
end
function tools.getCreatureId(vector)
tnames={}
rnames={}
--[[print("vector1 size:"..vector:size())
print("vector2 size:"..vector2:size())]]--
for i=0,vector:size()-1 do
--print(string.format("%x",vector:getval(i)))
local name=engine.peek(vector:getval(i),ptt_dfstring):getval()
local lid= tools.getlegendsid(vector:getval(i))
if lid ~=0 then
print(i..")*Creature Name:"..name.." race="..engine.peekw(vector:getval(i)+ptr_Creature.race.off).." legendid="..lid)
else
print(i..") Creature Name:"..name.." race="..engine.peekw(vector:getval(i)+ptr_Creature.race.off))
end
if name ~="" and name~=nil then
tnames[i]=name
rnames[name]=i
end
end
print("=====================================")
print("type in name or number:")
r=io.stdin:read()
if tonumber(r) ==nil then
indx=rnames[r]
if indx==nil then return end
else
r=tonumber(r)
if r<vector:size() then indx=r else return end
end
return indx
end
function tools.change_adv()
myoff=offsets.getEx("AdvCreatureVec")
vector=engine.peek(myoff,ptr_vector)
indx=tools.getCreatureId(vector)
print("Swaping, press enter when done or 'q' to stay, 's' to stay with legends id change")
tval=vector:getval(0)
vector:setval(0,vector:getval(indx))
vector:setval(indx,tval)
r=io.stdin:read()
if r=='q' then
return
end
if r~='s' then
tval=vector:getval(0)
vector:setval(0,vector:getval(indx))
vector:setval(indx,tval)
end
local lid=tools.getlegendsid(vector:getval(0))
if lid~=0 then
engine.poked(offsets.getEx("PlayerLegend"),lid)
else
print("Warning target does not have a valid legends id!")
end
end
tools.menu:add("Change Adventurer",tools.change_adv)
function tools.MakeFollow()
myoff=offsets.getEx("AdvCreatureVec")
vector=engine.peek(myoff,ptr_vector)
indx=tools.getCreatureId(vector)
print(string.format("current creature:%x",vector:getval(indx)))
trgid=engine.peek(vector:getval(0)+ptr_Creature.ID.off,DWORD)
lfollow=engine.peek(vector:getval(indx)+ptr_Creature.followID.off,DWORD)
if lfollow ~=0xFFFFFFFF then
print("Already following, unfollow? y/N")
r=io.stdin:read()
if r== "y" then
engine.poke(vector:getval(indx)+ptr_Creature.followID.off,DWORD,0)
end
else
engine.poke(vector:getval(indx)+ptr_Creature.followID.off,DWORD,trgid)
end
end
tools.menu:add("Make creature follow",tools.MakeFollow)
function tools.runscript(files)
if files==nil then
files={}
table.insert(files,io.stdin:read())
end
for _,v in pairs(files) do
print("Running script:"..v)
ParseScript(v)
end
end
function tools.getsite(names)
if words==nil then --do once its slow.
words,rwords=BuildWordTables()
end
if names==nil then
print("Type words that are in the site name, FULLCAPS, no modifiers (lovely->LOVE), q to quit:")
names={}
repeat
w=io.stdin:read();
if rwords[w]~=nil then
table.insert(names,w)
print("--added--")
end
until w=='q'
end
tnames={}
for _,v in pairs(names) do
if rwords[v] ~=nil then
table.insert(tnames,rwords[v]) --get word numbers
end
end
local offsites=engine.peekd(offsets.getEx("SiteData"))+0x120
snames={" pfort"," dfort"," cave","mohall","forest","hamlet","imploc"," lair"," fort"," camp"}
vector=engine.peek(offsites,ptr_vector)
print("Number of sites:"..vector:size())
print("List of hits:")
for i =0,vector:size()-1 do
off=vector:getval(i)
good=true
r=""
hits=0
sname=engine.peek(off,ptr_site.name)
for k=0,6 do
vnum=sname[k]--engine.peekd(off+0x38+k*4)
tgood=false
if vnum~=0xFFFFFFFF then
--print(string.format("%x",vnum))
if names[vnum]~=nil then
r=r..names[vnum].." "
end
for _,v in pairs(tnames) do
if vnum==v then
tgood=true
--print("Match")
hits=hits+1
break
end
end
if not tgood then
good=false
end
end
end
if(good) and (hits>0)then
--if true then
--print("=====================")
typ=engine.peek(off,ptr_site.type)--engine.peekw(off+0x78)
flg=engine.peekd(engine.peek(off,ptr_site.flagptr))
--flg=engine.peekd(off+224)
--flg2=engine.peekw(off)
--tv=engine.peek(off+0x84,ptr_vector)
--tv2=engine.peek(off+0xA4,ptr_vector)
print(string.format("%d)%s off=%x type=%s\t flags=%x",i,r,off,snames[typ+1],flg))
if i%100==99 then
r=io.stdin:read()
end
end
end
print("Type which to change (q cancels):")
repeat
r=io.stdin:read()
n=tonumber(r)
if(r=='q') then return end
until n~=nil
return vector:getval(n)
end
function tools.changesite(names)
off=tools.getsite(names)
snames={"Mountain halls (yours)","Dark fort","Cave","Mountain hall (NPC)","Forest retreat","Hamlet","Important location","Lair","Fort","Camp"}
print("Type in the site type (q cancels):")
for k,v in pairs(snames) do
print((k-1).."->"..v)
end
repeat
r=io.stdin:read()
n2=tonumber(r)
if(r=='q') then return end
until n2~=nil
--off=vector:getval(n)
print(string.format("%x->%d",off,n2))
engine.poke(off,ptr_site.type,n2)
end
function tools.changeflags(names)
myflag_pattern=ptt_dfflag.new(3*8)
off=tools.getsite(names)
offflgs=engine.peek(off,ptr_site.flagptr)
q=''
print(string.format("Site offset %x flags offset %x",off,offflgs))
repeat
print("flags:")
--off=vector:getval(n)
flg=engine.peek(offflgs,myflag_pattern)
r=""
for i=0,3*8-1 do
if flg:get(i)==1 then
r=r.."x"
else
r=r.."o"
end
if i%8==7 then
print(i-7 .."->"..r)
r=""
end
end
print("Type number to flip, or 'q' to quit.")
q=io.stdin:read()
n2=tonumber(q)
if n2~=nil then
flg:flip(n2)
engine.poke(offflgs,myflag_pattern,flg)
end
until q=='q'
end
function tools.hostilate()
vector=engine.peek(offsets.getEx("CreatureVec"),ptr_vector)
id=engine.peekd(offsets.getEx("CreaturePtr"))
print(string.format("Vec:%d cr:%d",vector:size(),id))
off=vector:getval(id)
crciv=engine.peek(off,ptr_Creature.civ)
print("Creatures civ:"..crciv)
curciv=engine.peekd(offsets.getEx("CurrentRace")-12)
print("My civ:"..curciv)
if curciv==crciv then
print("Friendly-making enemy")
engine.poke(off,ptr_Creature.civ,-1)
flg=engine.peek(off,ptr_Creature.flags)
flg:set(17,0)
print("flag 51:"..tostring(flg:get(51)))
engine.poke(off,ptr_Creature.flags,flg)
else
print("Enemy- making friendly")
engine.poke(off,ptr_Creature.civ,curciv)
flg=engine.peek(off,ptr_Creature.flags)
flg:set(17,1)
flg:set(19,0)
engine.poke(off,ptr_Creature.flags,flg)
end
end
function tools.mouseBlock()
local xs,ys,zs
xs,ys,zs=getxyz()
xs=math.floor(xs/16)
ys=math.floor(ys/16)
print("Mouse block is:"..xs.." "..ys.." "..zs)
end
function tools.protectsite()
local mapoffset=offsets.getEx("WorldData")--0x131C128+offsets.base()
local x=engine.peek(mapoffset+24,DWORD)
local y=engine.peek(mapoffset+28,DWORD)
local z=engine.peek(mapoffset+32,DWORD)
--vec=engine.peek(mapoffset,ptr_vector)
print("Blocks loaded:"..x.." "..y.." "..z)
print("Select type:")
print("1. All (SLOW)")
print("2. range (x0 x1 y0 y1 z0 z1)")
print("3. One block around pointer")
print("anything else- quit")
q=io.stdin:read()
n2=tonumber(q)
if n2==nil then return end
if n2>3 or n2<1 then return end
local xs,xe,ys,ye,zs,ze
if n2==1 then
xs=0
xe=x-1
ys=0
ye=y-1
zs=0
ze=z-1
elseif n2==2 then
print("enter x0:")
xs=tonumber(io.stdin:read())
print("enter x1:")
xe=tonumber(io.stdin:read())
print("enter y0:")
ys=tonumber(io.stdin:read())
print("enter y1:")
ye=tonumber(io.stdin:read())
print("enter z0:")
zs=tonumber(io.stdin:read())
print("enter z1:")
ze=tonumber(io.stdin:read())
function clamp(t,vmin,vmax)
if t> vmax then return vmax end
if t< vmin then return vmin end
return t
end
xs=clamp(xs,0,x-1)
ys=clamp(ys,0,y-1)
zs=clamp(zs,0,z-1)
xe=clamp(xe,xs,x-1)
ye=clamp(ye,ys,y-1)
ze=clamp(ze,zs,z-1)
else
xs,ys,zs=getxyz()
xs=math.floor(xs/16)
ys=math.floor(ys/16)
xe=xs
ye=ys
ze=zs
end
local xblocks=engine.peek(mapoffset,DWORD)
local flg=bit.lshift(1,14)
for xx=xs,xe do
local yblocks=engine.peek(xblocks+xx*4,DWORD)
for yy=ys,ye do
local zblocks=engine.peek(yblocks+yy*4,DWORD)
for zz=zs,ze do
local myblock=engine.peek(zblocks+zz*4,DWORD)
if myblock~=0 then
for i=0,255 do
local ff=engine.peek(myblock+0x67c+i*4,DWORD)
ff=bit.bor(ff,flg) --set 14 flag to 1
engine.poke(myblock+0x67c+i*4,DWORD,ff)
end
end
end
print("Blocks done:"..xx.." "..yy)
end
end
end
function tools.fixwarp()
local mapoffset=offsets.getEx("WorldData")--0x131C128+offsets.base()
local x=engine.peek(mapoffset+24,DWORD)
local y=engine.peek(mapoffset+28,DWORD)
local z=engine.peek(mapoffset+32,DWORD)
--vec=engine.peek(mapoffset,ptr_vector)
print("Blocks loaded:"..x.." "..y.." "..z)
print("Select type:")
print("1. All (SLOW)")
print("2. range (x0 x1 y0 y1 z0 z1)")
print("3. One block around pointer")
print("anything else- quit")
q=io.stdin:read()
n2=tonumber(q)
if n2==nil then return end
if n2>3 or n2<1 then return end
local xs,xe,ys,ye,zs,ze
if n2==1 then
xs=0
xe=x-1
ys=0
ye=y-1
zs=0
ze=z-1
elseif n2==2 then
print("enter x0:")
xs=tonumber(io.stdin:read())
print("enter x1:")
xe=tonumber(io.stdin:read())
print("enter y0:")
ys=tonumber(io.stdin:read())
print("enter y1:")
ye=tonumber(io.stdin:read())
print("enter z0:")
zs=tonumber(io.stdin:read())
print("enter z1:")
ze=tonumber(io.stdin:read())
function clamp(t,vmin,vmax)
if t> vmax then return vmax end
if t< vmin then return vmin end
return t
end
xs=clamp(xs,0,x-1)
ys=clamp(ys,0,y-1)
zs=clamp(zs,0,z-1)
xe=clamp(xe,xs,x-1)
ye=clamp(ye,ys,y-1)
ze=clamp(ze,zs,z-1)
else
xs,ys,zs=getxyz()
xs=math.floor(xs/16)
ys=math.floor(ys/16)
xe=xs
ye=ys
ze=zs
end
local xblocks=engine.peek(mapoffset,DWORD)
local flg=bit.bnot(bit.lshift(1,3))
for xx=xs,xe do
local yblocks=engine.peek(xblocks+xx*4,DWORD)
for yy=ys,ye do
local zblocks=engine.peek(yblocks+yy*4,DWORD)
for zz=zs,ze do
local myblock=engine.peek(zblocks+zz*4,DWORD)
if myblock~=0 then
for i=0,255 do
local ff=engine.peek(myblock+0x67c+i*4,DWORD)
ff=bit.band(ff,flg) --set 14 flag to 1
engine.poke(myblock+0x67c+i*4,DWORD,ff)
end
end
end
print("Blocks done:"..xx.." "..yy)
end
end
end
if not(FILE) then
tools.menu:add("Change site type",tools.changesite)
tools.menu:add("Change site flags",tools.changeflags)

@ -0,0 +1 @@
function findVectorsSized(size) local ret={} local text=GetTextRegion() for k,v in pairs(offsets.getvectors()) do if GetRegionIn2(k)~=nil then --if v>4 then local tv=engine.peek(k,ptr_vector) if tv:size() == size then print(string.format("%x is size %d",k,size)) table.insert(ret,k) end end end return ret end function findMaterial(mattype,matname) --currently only stones local tbl=BuildMaterialTable() return tbl[matname] end

@ -0,0 +1,39 @@
#include "lua_FunctionCall.h"
using namespace lua;
int lua_FunctionCall(lua_State *L)
{
lua::state st(L);
FunctionCaller cl(0);
size_t ptr=st.as<size_t>(1);
int callconv=st.as<size_t>(2);
vector<int> arguments;
for(int i=3;i<st.gettop();i++)
arguments.push_back(st.as<int>(i));
int ret=cl.CallFunction(ptr,(FunctionCaller::callconv)callconv,arguments);
st.push(ret);
return 1;// dunno if len is needed...
}
const luaL_Reg lua_functioncall_func[]=
{
{"call",lua_FunctionCall},
{NULL,NULL}
};
#define __ADDCONST(name) st.push(::FunctionCaller:: name); st.setglobal(#name)
void lua::RegisterFunctionCall(lua::state &st)
{
st.getglobal("FunctionCall");
if(st.is<lua::nil>())
{
st.pop();
st.newtable();
}
__ADDCONST(STD_CALL);
__ADDCONST(FAST_CALL);
__ADDCONST(THIS_CALL);
__ADDCONST(CDECL_CALL);
lua::RegFunctionsLocal(st, lua_functioncall_func);
st.setglobal("FunctionCall");
}
#undef __ADDCONST

@ -96,6 +96,29 @@ int OffsetGroup::getParent(lua_State *L)
st.pcall(2,1);
return 1;
}
int OffsetGroup::getKeys(lua_State *L)
{
const char* invalids[]={"notset","invalid","valid"};
const char* keytypes[]={"offset","address","hexval","string","group"};
lua::state st(L);
std::vector<DFHack::OffsetKey> t= p->getKeys();
st.newtable();
for(size_t i=0;i<t.size();i++)
{
st.push(i);
st.newtable();
st.push(invalids[t[i].inval]);
st.setfield("invalid");
st.push(t[i].key);
st.setfield("key");
st.push(keytypes[t[i].keytype]);//maybe use int...
st.setfield("keytype");
st.settable();
}
return 1;
}
}
IMP_LUNE(lua::OffsetGroup,OffsetGroup);
LUNE_METHODS_START(lua::OffsetGroup)
@ -112,6 +135,7 @@ LUNE_METHODS_START(lua::OffsetGroup)
method(lua::OffsetGroup,getName),
method(lua::OffsetGroup,getFullName),
method(lua::OffsetGroup,getParent),
method(lua::OffsetGroup,getKeys),
LUNE_METHODS_END();
// VersionInfo Stuff
static int __lua_getMD5(lua_State *S)
@ -326,12 +350,23 @@ static int __lua_getHexValue(lua_State *S)
static int __lua_getGroup(lua_State *S)
{
lua::state st(S);
DFHack::OffsetGroup* t= DFHack::Core::getInstance().vinfo->getGroup(st.as<std::string>(1));
st.getglobal("OffsetGroup");
st.getfield("new");
st.getglobal("OffsetGroup");
st.pushlightuserdata(t);
st.pcall(2,1);
if(st.as<std::string>(1)=="") //if no argument, return version info as a groupoffset (dynamic cast)
{
st.getglobal("OffsetGroup");
st.getfield("new");
st.getglobal("OffsetGroup");
st.pushlightuserdata(dynamic_cast<DFHack::OffsetGroup*>(DFHack::Core::getInstance().vinfo));
st.pcall(2,1);
}
else
{
DFHack::OffsetGroup* t= DFHack::Core::getInstance().vinfo->getGroup(st.as<std::string>(1));
st.getglobal("OffsetGroup");
st.getfield("new");
st.getglobal("OffsetGroup");
st.pushlightuserdata(t);
st.pcall(2,1);
}
return 1;
}
static int __lua_getParent(lua_State *S)