Merge remote-tracking branch 'angavrilov/master'
commit
2a0171a4ff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,121 @@
|
|||||||
|
-- Simple binary patch with IDA dif file support.
|
||||||
|
|
||||||
|
local function load_patch(name)
|
||||||
|
local filename = name
|
||||||
|
if not string.match(filename, '[./\\]') then
|
||||||
|
filename = dfhack.getHackPath()..'/patches/'..dfhack.getDFVersion()..'/'..name..'.dif'
|
||||||
|
end
|
||||||
|
|
||||||
|
local file, err = io.open(filename, 'r')
|
||||||
|
if not file then
|
||||||
|
if string.match(err, ': No such file or directory') then
|
||||||
|
return nil, 'patch not found'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local old_bytes = {}
|
||||||
|
local new_bytes = {}
|
||||||
|
|
||||||
|
for line in file:lines() do
|
||||||
|
if string.match(line, '^%x+:') then
|
||||||
|
local offset, oldv, newv = string.match(line, '^(%x+):%s*(%x+)%s+(%x+)%s*$')
|
||||||
|
if not offset then
|
||||||
|
file:close()
|
||||||
|
return nil, 'could not parse: '..line
|
||||||
|
end
|
||||||
|
|
||||||
|
offset, oldv, newv = tonumber(offset,16), tonumber(oldv,16), tonumber(newv,16)
|
||||||
|
if oldv > 255 or newv > 255 then
|
||||||
|
file:close()
|
||||||
|
return nil, 'invalid byte values: '..line
|
||||||
|
end
|
||||||
|
|
||||||
|
old_bytes[offset] = oldv
|
||||||
|
new_bytes[offset] = newv
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return { name = name, old_bytes = old_bytes, new_bytes = new_bytes }
|
||||||
|
end
|
||||||
|
|
||||||
|
local function rebase_table(input)
|
||||||
|
local output = {}
|
||||||
|
local base = dfhack.internal.getImageBase()
|
||||||
|
for k,v in pairs(input) do
|
||||||
|
local offset = dfhack.internal.adjustOffset(k)
|
||||||
|
if not offset then
|
||||||
|
return nil, string.format('invalid offset: %x', k)
|
||||||
|
end
|
||||||
|
output[base + offset] = v
|
||||||
|
end
|
||||||
|
return output
|
||||||
|
end
|
||||||
|
|
||||||
|
local function rebase_patch(patch)
|
||||||
|
local nold, err = rebase_table(patch.old_bytes)
|
||||||
|
if not nold then return nil, err end
|
||||||
|
local nnew, err = rebase_table(patch.new_bytes)
|
||||||
|
if not nnew then return nil, err end
|
||||||
|
return { name = patch.name, old_bytes = nold, new_bytes = nnew }
|
||||||
|
end
|
||||||
|
|
||||||
|
BinaryPatch = defclass(BinaryPatch)
|
||||||
|
|
||||||
|
BinaryPatch.ATTRS {
|
||||||
|
name = DEFAULT_NIL,
|
||||||
|
old_bytes = DEFAULT_NIL,
|
||||||
|
new_bytes = DEFAULT_NIL,
|
||||||
|
}
|
||||||
|
|
||||||
|
function load_dif_file(name)
|
||||||
|
local patch, err = load_patch(name)
|
||||||
|
if not patch then return nil, err end
|
||||||
|
|
||||||
|
local rpatch, err = rebase_patch(patch)
|
||||||
|
if not rpatch then return nil, err end
|
||||||
|
|
||||||
|
return BinaryPatch(rpatch)
|
||||||
|
end
|
||||||
|
|
||||||
|
function BinaryPatch:status()
|
||||||
|
local old_ok, err, addr = dfhack.internal.patchBytes({}, self.old_bytes)
|
||||||
|
if old_ok then
|
||||||
|
return 'removed'
|
||||||
|
elseif dfhack.internal.patchBytes({}, self.new_bytes) then
|
||||||
|
return 'applied'
|
||||||
|
else
|
||||||
|
return 'conflict', addr
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function BinaryPatch:isApplied()
|
||||||
|
return dfhack.internal.patchBytes({}, self.new_bytes)
|
||||||
|
end
|
||||||
|
|
||||||
|
function BinaryPatch:apply()
|
||||||
|
local ok, err, addr = dfhack.internal.patchBytes(self.new_bytes, self.old_bytes)
|
||||||
|
if ok then
|
||||||
|
return true, 'applied the patch'
|
||||||
|
elseif dfhack.internal.patchBytes({}, self.new_bytes) then
|
||||||
|
return true, 'patch is already applied'
|
||||||
|
else
|
||||||
|
return false, string.format('conflict at address %x', addr)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function BinaryPatch:isRemoved()
|
||||||
|
return dfhack.internal.patchBytes({}, self.old_bytes)
|
||||||
|
end
|
||||||
|
|
||||||
|
function BinaryPatch:remove()
|
||||||
|
local ok, err, addr = dfhack.internal.patchBytes(self.old_bytes, self.new_bytes)
|
||||||
|
if ok then
|
||||||
|
return true, 'removed the patch'
|
||||||
|
elseif dfhack.internal.patchBytes({}, self.old_bytes) then
|
||||||
|
return true, 'patch is already removed'
|
||||||
|
else
|
||||||
|
return false, string.format('conflict at address %x', addr)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return _ENV
|
@ -1 +1 @@
|
|||||||
Subproject commit fcacacce7cf09cf70f011fea87b5be416da73457
|
Subproject commit 9b4dc47a54c8b15db2f30fbf926deb8c1bf992f6
|
@ -0,0 +1,142 @@
|
|||||||
|
http://www.bay12games.com/dwarves/mantisbt/view.php?id=1445
|
||||||
|
|
||||||
|
0x2ac6b
|
||||||
|
CC CC CC CC CC
|
||||||
|
66 39 E8 EB 53
|
||||||
|
|
||||||
|
.text:0042B86B loc_42B86B:
|
||||||
|
.text:0042B86B cmp ax, bp
|
||||||
|
.text:0042B86E jmp short loc_42B8C3
|
||||||
|
|
||||||
|
0x2ac7b
|
||||||
|
CC CC CC CC CC
|
||||||
|
E9 96 A2 00 00
|
||||||
|
|
||||||
|
.text:0042B87B loc_42B87B:
|
||||||
|
.text:0042B87B jmp loc_435B16
|
||||||
|
|
||||||
|
0x2acc3
|
||||||
|
CC CC CC CC CC CC CC CC CC CC CC CC CC
|
||||||
|
75 0A 66 FF 4C 24 16 79 03 58 EB AC C3
|
||||||
|
|
||||||
|
.text:0042B8C3 loc_42B8C3:
|
||||||
|
.text:0042B8C3 jnz short locret_42B8CF
|
||||||
|
.text:0042B8C5 dec word ptr [esp+16h] ; 4+8+8+2
|
||||||
|
.text:0042B8CA jns short locret_42B8CF
|
||||||
|
.text:0042B8CC pop eax
|
||||||
|
.text:0042B8CD jmp short loc_42B87B
|
||||||
|
.text:0042B8CF locret_42B8CF:
|
||||||
|
.text:0042B8CF retn
|
||||||
|
|
||||||
|
0x2b2a1
|
||||||
|
CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
|
||||||
|
66 C7 44 24 0E 01 00 8B 90 44 01 00 00 C3 CC
|
||||||
|
|
||||||
|
.text:0042BEA1 loc_42BEA1:
|
||||||
|
.text:0042BEA1 mov word ptr [esp+0Eh], 1 ; 4+8+2
|
||||||
|
.text:0042BEA8 mov edx, [eax+144h]
|
||||||
|
.text:0042BEAE retn
|
||||||
|
|
||||||
|
0x34d91
|
||||||
|
8B 90 44 01 00 00
|
||||||
|
E8 0B 65 FF FF 90
|
||||||
|
|
||||||
|
<<<<
|
||||||
|
.text:00435991 mov edx, [eax+144h]
|
||||||
|
====
|
||||||
|
.text:00435991 call loc_42BEA1
|
||||||
|
.text:00435996 nop
|
||||||
|
>>>>
|
||||||
|
|
||||||
|
0x34e53
|
||||||
|
0F 84 BD 00 00 00
|
||||||
|
E8 6B 5E FF FF 90
|
||||||
|
|
||||||
|
<<<<
|
||||||
|
.text:00435A53 jz loc_435B16
|
||||||
|
====
|
||||||
|
.text:00435A53 call loc_42B8C3
|
||||||
|
.text:00435A58 nop
|
||||||
|
>>>>
|
||||||
|
|
||||||
|
0x34ef3
|
||||||
|
66 3B C5 74 1E
|
||||||
|
E8 73 5D FF FF
|
||||||
|
|
||||||
|
<<<<
|
||||||
|
.text:00435AF3 cmp ax, bp
|
||||||
|
.text:00435AF6 jz short loc_435B16
|
||||||
|
====
|
||||||
|
.text:00435AF3 call loc_42B86B
|
||||||
|
>>>>
|
||||||
|
|
||||||
|
|
||||||
|
basically:
|
||||||
|
|
||||||
|
+ int allowed_count = 1; // to mean 2
|
||||||
|
...
|
||||||
|
- if (type(item) == new_type)
|
||||||
|
+ if (type(item) == new_type && --allowed_count < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
to allow up to two items of the same type at the same time
|
||||||
|
|
||||||
|
|
||||||
|
---8<---
|
||||||
|
This difference file is created by The Interactive Disassembler
|
||||||
|
|
||||||
|
Dwarf Fortress.exe
|
||||||
|
0002AC6B: CC 66
|
||||||
|
0002AC6C: CC 39
|
||||||
|
0002AC6D: CC E8
|
||||||
|
0002AC6E: CC EB
|
||||||
|
0002AC6F: CC 53
|
||||||
|
0002AC7B: CC E9
|
||||||
|
0002AC7C: CC 96
|
||||||
|
0002AC7D: CC A2
|
||||||
|
0002AC7E: CC 00
|
||||||
|
0002AC7F: CC 00
|
||||||
|
0002ACC3: CC 75
|
||||||
|
0002ACC4: CC 0A
|
||||||
|
0002ACC5: CC 66
|
||||||
|
0002ACC6: CC FF
|
||||||
|
0002ACC7: CC 4C
|
||||||
|
0002ACC8: CC 24
|
||||||
|
0002ACC9: CC 16
|
||||||
|
0002ACCA: CC 79
|
||||||
|
0002ACCB: CC 03
|
||||||
|
0002ACCC: CC 58
|
||||||
|
0002ACCD: CC EB
|
||||||
|
0002ACCE: CC AC
|
||||||
|
0002ACCF: CC C3
|
||||||
|
0002B2A1: CC 66
|
||||||
|
0002B2A2: CC C7
|
||||||
|
0002B2A3: CC 44
|
||||||
|
0002B2A4: CC 24
|
||||||
|
0002B2A5: CC 0E
|
||||||
|
0002B2A6: CC 01
|
||||||
|
0002B2A7: CC 00
|
||||||
|
0002B2A8: CC 8B
|
||||||
|
0002B2A9: CC 90
|
||||||
|
0002B2AA: CC 44
|
||||||
|
0002B2AB: CC 01
|
||||||
|
0002B2AC: CC 00
|
||||||
|
0002B2AD: CC 00
|
||||||
|
0002B2AE: CC C3
|
||||||
|
00034D91: 8B E8
|
||||||
|
00034D92: 90 0B
|
||||||
|
00034D93: 44 65
|
||||||
|
00034D94: 01 FF
|
||||||
|
00034D95: 00 FF
|
||||||
|
00034D96: 00 90
|
||||||
|
00034E53: 0F E8
|
||||||
|
00034E54: 84 6B
|
||||||
|
00034E55: BD 5E
|
||||||
|
00034E56: 00 FF
|
||||||
|
00034E57: 00 FF
|
||||||
|
00034E58: 00 90
|
||||||
|
00034EF3: 66 E8
|
||||||
|
00034EF4: 3B 73
|
||||||
|
00034EF5: C5 5D
|
||||||
|
00034EF6: 74 FF
|
||||||
|
00034EF7: 1E FF
|
@ -0,0 +1,91 @@
|
|||||||
|
http://www.bay12games.com/dwarves/mantisbt/view.php?id=808
|
||||||
|
|
||||||
|
Original code:
|
||||||
|
|
||||||
|
.text:00916BCE mov edi, ebp
|
||||||
|
.text:00916BD0 call eax
|
||||||
|
.text:00916BD2 test eax, eax
|
||||||
|
.text:00916BD4 jnz short loc_916C1C
|
||||||
|
|
||||||
|
.text:00916C0A mov edi, ebp
|
||||||
|
|
||||||
|
.text:00916C14 mov edi, ebp
|
||||||
|
|
||||||
|
Patch:
|
||||||
|
|
||||||
|
0x2ac34:
|
||||||
|
CC CC CC CC CC CC CC CC CC CC CC CC
|
||||||
|
8B 7C 24 78 8B 3C B7 FF D0 EB 25 CC
|
||||||
|
|
||||||
|
.text:0042B834 loc_42B834:
|
||||||
|
.text:0042B834 mov edi, [esp+78h]
|
||||||
|
.text:0042B838 mov edi, [edi+esi*4]
|
||||||
|
.text:0042B83B call eax
|
||||||
|
.text:0042B83D jmp short unk_42B864
|
||||||
|
|
||||||
|
0x2ac64
|
||||||
|
CC CC CC CC CC CC CC CC CC CC CC CC
|
||||||
|
85 C0 E9 69 B3 4E 00 CC CC CC CC CC
|
||||||
|
|
||||||
|
.text:0042B864 loc_42B864:
|
||||||
|
.text:0042B864 test eax, eax
|
||||||
|
.text:0042B866 jmp loc_916BD4
|
||||||
|
|
||||||
|
0x515fce
|
||||||
|
8B FD FF D0 85 C0
|
||||||
|
E9 61 4C B1 FF 90
|
||||||
|
|
||||||
|
.text:00916BCE jmp loc_42B834
|
||||||
|
.text:00916BD3 nop
|
||||||
|
.text:00916BD4 loc_916BD4:
|
||||||
|
|
||||||
|
0x51600a
|
||||||
|
8B FD
|
||||||
|
90 90
|
||||||
|
|
||||||
|
.text:00916C0A nop
|
||||||
|
.text:00916C0B nop
|
||||||
|
|
||||||
|
0x516014
|
||||||
|
8B FD
|
||||||
|
90 90
|
||||||
|
|
||||||
|
.text:00916C14 nop
|
||||||
|
.text:00916C15 nop
|
||||||
|
|
||||||
|
|
||||||
|
You can use this script to apply the generated patch below:
|
||||||
|
http://stalkr.net/files/ida/idadif.py
|
||||||
|
|
||||||
|
----8<----
|
||||||
|
This difference file is created by The Interactive Disassembler
|
||||||
|
|
||||||
|
Dwarf Fortress.exe
|
||||||
|
0002AC34: CC 8B
|
||||||
|
0002AC35: CC 7C
|
||||||
|
0002AC36: CC 24
|
||||||
|
0002AC37: CC 78
|
||||||
|
0002AC38: CC 8B
|
||||||
|
0002AC39: CC 3C
|
||||||
|
0002AC3A: CC B7
|
||||||
|
0002AC3B: CC FF
|
||||||
|
0002AC3C: CC D0
|
||||||
|
0002AC3D: CC EB
|
||||||
|
0002AC3E: CC 25
|
||||||
|
0002AC64: CC 85
|
||||||
|
0002AC65: CC C0
|
||||||
|
0002AC66: CC E9
|
||||||
|
0002AC67: CC 69
|
||||||
|
0002AC68: CC B3
|
||||||
|
0002AC69: CC 4E
|
||||||
|
0002AC6A: CC 00
|
||||||
|
00515FCE: 8B E9
|
||||||
|
00515FCF: FD 61
|
||||||
|
00515FD0: FF 4C
|
||||||
|
00515FD1: D0 B1
|
||||||
|
00515FD2: 85 FF
|
||||||
|
00515FD3: C0 90
|
||||||
|
0051600A: 8B 90
|
||||||
|
0051600B: FD 90
|
||||||
|
00516014: 8B 90
|
||||||
|
00516015: FD 90
|
@ -0,0 +1,61 @@
|
|||||||
|
http://www.bay12games.com/dwarves/mantisbt/view.php?id=5994
|
||||||
|
|
||||||
|
Original code:
|
||||||
|
|
||||||
|
.text:008629BD mov edi, [eax+38h]
|
||||||
|
.text:008629C0 mov eax, [eax+3Ch]
|
||||||
|
.text:008629C3 mov [esp+1Ch], eax
|
||||||
|
.text:008629C7 cmp edi, eax
|
||||||
|
.text:008629C9 jnb short loc_862A22
|
||||||
|
.text:008629CB jmp short loc_8629D0
|
||||||
|
.text:008629CD lea ecx, [ecx+0]
|
||||||
|
...
|
||||||
|
.text:00862A19 add edi, 4
|
||||||
|
.text:00862A1C cmp edi, [esp+1Ch]
|
||||||
|
.text:00862A20 jb short loc_8629D0
|
||||||
|
|
||||||
|
Patch:
|
||||||
|
|
||||||
|
0x461dbd
|
||||||
|
8B 78 38 8B 40 3C 89 44 24 1C 3B F8
|
||||||
|
8B 78 3C 8B 40 38 89 44 24 1C 39 F8
|
||||||
|
|
||||||
|
.text:008629BD mov edi, [eax+3Ch]
|
||||||
|
.text:008629C0 mov eax, [eax+38h]
|
||||||
|
.text:008629C3 mov [esp+1Ch], eax
|
||||||
|
.text:008629C7 cmp eax, edi
|
||||||
|
|
||||||
|
0x461dcb
|
||||||
|
EB 03 8D 49 00
|
||||||
|
83 EF 04 90 90
|
||||||
|
|
||||||
|
.text:008629CB sub edi, 4
|
||||||
|
.text:008629CE nop
|
||||||
|
.text:008629CF nop
|
||||||
|
|
||||||
|
0x461e19
|
||||||
|
83 C7 04 3B 7C 24 1C 72 AE
|
||||||
|
83 EF 04 3B 7C 24 1C 73 AE
|
||||||
|
|
||||||
|
.text:00862A19 sub edi, 4
|
||||||
|
.text:00862A1C cmp edi, [esp+1Ch]
|
||||||
|
.text:00862A20 jnb short loc_8629D0
|
||||||
|
|
||||||
|
|
||||||
|
You can use this script to apply the generated patch below:
|
||||||
|
http://stalkr.net/files/ida/idadif.py
|
||||||
|
|
||||||
|
----8<----
|
||||||
|
This difference file is created by The Interactive Disassembler
|
||||||
|
|
||||||
|
Dwarf_Fortress
|
||||||
|
00461DBF: 38 3C
|
||||||
|
00461DC2: 3C 38
|
||||||
|
00461DC7: 3B 39
|
||||||
|
00461DCB: EB 83
|
||||||
|
00461DCC: 03 EF
|
||||||
|
00461DCD: 8D 04
|
||||||
|
00461DCE: 49 90
|
||||||
|
00461DCF: 00 90
|
||||||
|
00461E1A: C7 EF
|
||||||
|
00461E20: 72 73
|
@ -0,0 +1,104 @@
|
|||||||
|
http://www.bay12games.com/dwarves/mantisbt/view.php?id=5994
|
||||||
|
|
||||||
|
0x461de2
|
||||||
|
F6 46 0C 01 74 31
|
||||||
|
E9 0A 8E BC FF 90
|
||||||
|
|
||||||
|
.text:008629E2 jmp near ptr loc_42B7F1 ; << CAVE
|
||||||
|
.text:008629E7 nop
|
||||||
|
.text:008629E8 loc_8629E8:
|
||||||
|
|
||||||
|
0x2abf1
|
||||||
|
CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
|
||||||
|
8B 4C 24 2C F6 46 0C 01 75 08 E9 19 72 43 00
|
||||||
|
|
||||||
|
.text:0042B7F1 loc_42B7F1:
|
||||||
|
.text:0042B7F1 mov ecx, [esp+2Ch] ; job
|
||||||
|
.text:0042B7F5 test byte ptr [esi+0Ch], 1
|
||||||
|
.text:0042B7F9 jnz short near ptr loc_42B803
|
||||||
|
.text:0042B7FB coord_test_jfail:
|
||||||
|
.text:0042B7FB jmp loc_862A19
|
||||||
|
|
||||||
|
0x2ac03
|
||||||
|
CC CC CC CC CC CC CC CC CC CC CC CC CC
|
||||||
|
8B 41 10 3B 46 04 75 F0 EB 06 CC CC CC
|
||||||
|
|
||||||
|
.text:0042B803 loc_42B803:
|
||||||
|
.text:0042B803 mov eax, [ecx+10h] ; job->pos.(x,y)
|
||||||
|
.text:0042B806 cmp eax, [esi+4] ; item->pos.(x,y)
|
||||||
|
.text:0042B809 jnz short coord_test_jfail
|
||||||
|
.text:0042B80B jmp short near ptr loc_42B813
|
||||||
|
|
||||||
|
0x2ac13
|
||||||
|
CC CC CC CC CC CC CC CC CC CC CC CC CC
|
||||||
|
66 8B 41 14 66 3B 46 08 75 DE EB 06 CC
|
||||||
|
|
||||||
|
text:0042B813 loc_42B813:
|
||||||
|
.text:0042B813 mov ax, [ecx+14h] ; job->pos.z
|
||||||
|
.text:0042B817 cmp ax, [esi+8] ; item->pos.z
|
||||||
|
.text:0042B81B jnz short coord_test_jfail
|
||||||
|
.text:0042B81D jmp short near ptr loc_42B825
|
||||||
|
|
||||||
|
0x2ac25
|
||||||
|
CC CC CC CC CC CC CC CC CC CC CC
|
||||||
|
E9 BE 71 43 00 CC CC CC CC CC CC
|
||||||
|
|
||||||
|
.text:0042B825 loc_42B825:
|
||||||
|
.text:0042B825 jmp loc_8629E8
|
||||||
|
|
||||||
|
|
||||||
|
You can use this script to apply the generated patch below:
|
||||||
|
http://stalkr.net/files/ida/idadif.py
|
||||||
|
|
||||||
|
----8<----
|
||||||
|
This difference file is created by The Interactive Disassembler
|
||||||
|
|
||||||
|
Dwarf Fortress.exe
|
||||||
|
0002ABF1: CC 8B
|
||||||
|
0002ABF2: CC 4C
|
||||||
|
0002ABF3: CC 24
|
||||||
|
0002ABF4: CC 2C
|
||||||
|
0002ABF5: CC F6
|
||||||
|
0002ABF6: CC 46
|
||||||
|
0002ABF7: CC 0C
|
||||||
|
0002ABF8: CC 01
|
||||||
|
0002ABF9: CC 75
|
||||||
|
0002ABFA: CC 08
|
||||||
|
0002ABFB: CC E9
|
||||||
|
0002ABFC: CC 19
|
||||||
|
0002ABFD: CC 72
|
||||||
|
0002ABFE: CC 43
|
||||||
|
0002ABFF: CC 00
|
||||||
|
0002AC03: CC 8B
|
||||||
|
0002AC04: CC 41
|
||||||
|
0002AC05: CC 10
|
||||||
|
0002AC06: CC 3B
|
||||||
|
0002AC07: CC 46
|
||||||
|
0002AC08: CC 04
|
||||||
|
0002AC09: CC 75
|
||||||
|
0002AC0A: CC F0
|
||||||
|
0002AC0B: CC EB
|
||||||
|
0002AC0C: CC 06
|
||||||
|
0002AC13: CC 66
|
||||||
|
0002AC14: CC 8B
|
||||||
|
0002AC15: CC 41
|
||||||
|
0002AC16: CC 14
|
||||||
|
0002AC17: CC 66
|
||||||
|
0002AC18: CC 3B
|
||||||
|
0002AC19: CC 46
|
||||||
|
0002AC1A: CC 08
|
||||||
|
0002AC1B: CC 75
|
||||||
|
0002AC1C: CC DE
|
||||||
|
0002AC1D: CC EB
|
||||||
|
0002AC1E: CC 06
|
||||||
|
0002AC25: CC E9
|
||||||
|
0002AC26: CC BE
|
||||||
|
0002AC27: CC 71
|
||||||
|
0002AC28: CC 43
|
||||||
|
0002AC29: CC 00
|
||||||
|
00461DE2: F6 E9
|
||||||
|
00461DE3: 46 0A
|
||||||
|
00461DE4: 0C 8E
|
||||||
|
00461DE5: 01 BC
|
||||||
|
00461DE6: 74 FF
|
||||||
|
00461DE7: 31 90
|
@ -0,0 +1,62 @@
|
|||||||
|
http://www.bay12games.com/dwarves/mantisbt/view.php?id=4406
|
||||||
|
|
||||||
|
1. Include store in hospital jobs when recomputing counters
|
||||||
|
|
||||||
|
0x68a63
|
||||||
|
0F 85 58 01 00 00
|
||||||
|
90 90 90 90 90 90
|
||||||
|
|
||||||
|
<<<<
|
||||||
|
.text:00469663 jnz loc_4697C1
|
||||||
|
====
|
||||||
|
.text:00469663 nop
|
||||||
|
.text:00469664 nop
|
||||||
|
.text:00469665 nop
|
||||||
|
.text:00469666 nop
|
||||||
|
.text:00469667 nop
|
||||||
|
.text:00469668 nop
|
||||||
|
>>>>
|
||||||
|
|
||||||
|
- if (job->getBuildingRef(BUILDING_DESTINATION) != this) continue;
|
||||||
|
+ // NOP
|
||||||
|
|
||||||
|
This reference points to the containers, not the hospital civzone.
|
||||||
|
Since fixing this properly is too hard for a patch, just remove the
|
||||||
|
check. Most people have only one hospital anyway, and it is better
|
||||||
|
to err on the side of caution here.
|
||||||
|
|
||||||
|
|
||||||
|
2. Make the stockpiling code increment the right stock counters
|
||||||
|
|
||||||
|
0x3dcbf9
|
||||||
|
8B 0C 90 8B 81 80 00 00 00
|
||||||
|
8B 3C 90 8B 87 80 00 00 00
|
||||||
|
|
||||||
|
<<<<
|
||||||
|
.text:007DD7F9 mov ecx, [eax+edx*4]
|
||||||
|
.text:007DD7FC mov eax, [ecx+80h]
|
||||||
|
====
|
||||||
|
.text:007DD7F9 mov edi, [eax+edx*4]
|
||||||
|
.text:007DD7FC mov eax, [edi+80h]
|
||||||
|
>>>>
|
||||||
|
|
||||||
|
- id = civzones[i]->children[child_idx[i]]->id
|
||||||
|
+ cur_civzone = civzones[i] // existing var from previous loop
|
||||||
|
+ id = cur_civzone->children[child_idx[i]]->id
|
||||||
|
|
||||||
|
The reason being, later code uses that var (at this point containing
|
||||||
|
useless data) to increment counters and amounts in the hospital.
|
||||||
|
|
||||||
|
|
||||||
|
---8<---
|
||||||
|
This difference file is created by The Interactive Disassembler
|
||||||
|
|
||||||
|
Dwarf Fortress.exe
|
||||||
|
00068A63: 0F 90
|
||||||
|
00068A64: 85 90
|
||||||
|
00068A65: 58 90
|
||||||
|
00068A66: 01 90
|
||||||
|
00068A67: 00 90
|
||||||
|
00068A68: 00 90
|
||||||
|
003DCBFA: 0C 3C
|
||||||
|
003DCBFD: 81 87
|
@ -0,0 +1,83 @@
|
|||||||
|
http://www.bay12games.com/dwarves/mantisbt/view.php?id=4530
|
||||||
|
|
||||||
|
0x2ac85
|
||||||
|
CC CC CC CC CC CC CC CC CC CC CC
|
||||||
|
29 44 24 24 8B 9D 28 01 00 00 C3
|
||||||
|
|
||||||
|
.text:0042B885 loc_42B885:
|
||||||
|
.text:0042B885 sub [esp+24h], eax
|
||||||
|
.text:0042B889 mov ebx, [ebp+128h]
|
||||||
|
.text:0042B88F retn
|
||||||
|
|
||||||
|
0x2ac94
|
||||||
|
CC CC CC CC CC CC CC CC CC CC CC CC
|
||||||
|
89 C1 8B 00 FF 90 34 02 00 00 EB E5
|
||||||
|
|
||||||
|
.text:0042B894 loc_42B894:
|
||||||
|
.text:0042B894 mov ecx, eax
|
||||||
|
.text:0042B896 mov eax, [eax]
|
||||||
|
.text:0042B898 call dword ptr [eax+234h]
|
||||||
|
.text:0042B89E jmp short loc_42B885
|
||||||
|
|
||||||
|
0x6e28ff
|
||||||
|
29 44 24 20
|
||||||
|
90 90 90 90
|
||||||
|
|
||||||
|
<<<<
|
||||||
|
.text:00AE34FF sub [esp+20h], eax
|
||||||
|
====
|
||||||
|
.text:00AE34FF nop
|
||||||
|
.text:00AE3500 nop
|
||||||
|
.text:00AE3501 nop
|
||||||
|
.text:00AE3502 nop
|
||||||
|
>>>>
|
||||||
|
|
||||||
|
0x6e2999
|
||||||
|
8B 9D 28 01 00 00
|
||||||
|
E8 F6 82 94 FF 90
|
||||||
|
|
||||||
|
<<<<
|
||||||
|
.text:00AE3599 mov ebx, [ebp+128h]
|
||||||
|
====
|
||||||
|
.text:00AE3599 call loc_42B894
|
||||||
|
.text:00AE359E nop
|
||||||
|
>>>>
|
||||||
|
|
||||||
|
---8<---
|
||||||
|
This difference file is created by The Interactive Disassembler
|
||||||
|
|
||||||
|
Dwarf Fortress.exe
|
||||||
|
0002AC85: CC 29
|
||||||
|
0002AC86: CC 44
|
||||||
|
0002AC87: CC 24
|
||||||
|
0002AC88: CC 24
|
||||||
|
0002AC89: CC 8B
|
||||||
|
0002AC8A: CC 9D
|
||||||
|
0002AC8B: CC 28
|
||||||
|
0002AC8C: CC 01
|
||||||
|
0002AC8D: CC 00
|
||||||
|
0002AC8E: CC 00
|
||||||
|
0002AC8F: CC C3
|
||||||
|
0002AC94: CC 89
|
||||||
|
0002AC95: CC C1
|
||||||
|
0002AC96: CC 8B
|
||||||
|
0002AC97: CC 00
|
||||||
|
0002AC98: CC FF
|
||||||
|
0002AC99: CC 90
|
||||||
|
0002AC9A: CC 34
|
||||||
|
0002AC9B: CC 02
|
||||||
|
0002AC9C: CC 00
|
||||||
|
0002AC9D: CC 00
|
||||||
|
0002AC9E: CC EB
|
||||||
|
0002AC9F: CC E5
|
||||||
|
006E28FF: 29 90
|
||||||
|
006E2900: 44 90
|
||||||
|
006E2901: 24 90
|
||||||
|
006E2902: 20 90
|
||||||
|
006E2999: 8B E8
|
||||||
|
006E299A: 9D F6
|
||||||
|
006E299B: 28 82
|
||||||
|
006E299C: 01 94
|
||||||
|
006E299D: 00 FF
|
||||||
|
006E299E: 00 90
|
||||||
|
|
@ -0,0 +1,61 @@
|
|||||||
|
http://www.bay12games.com/dwarves/mantisbt/view.php?id=1445
|
||||||
|
|
||||||
|
0x4c05c4
|
||||||
|
8B 8C 24 80 00 00 00
|
||||||
|
89 C1 90 90 90 90 90
|
||||||
|
|
||||||
|
<<<<
|
||||||
|
.text:008C11C4 mov ecx, [esp+98h+var_18]
|
||||||
|
====
|
||||||
|
.text:008C11C4 mov ecx, eax
|
||||||
|
.text:008C11C6 nop
|
||||||
|
.text:008C11C7 nop
|
||||||
|
.text:008C11C8 nop
|
||||||
|
.text:008C11C9 nop
|
||||||
|
.text:008C11CA nop
|
||||||
|
>>>>
|
||||||
|
|
||||||
|
0x4c06a1
|
||||||
|
8B 8C 24 80 00 00 00
|
||||||
|
89 C1 90 90 90 90 90
|
||||||
|
|
||||||
|
<<<<
|
||||||
|
.text:008C12A1 mov ecx, [esp+98h+var_18]
|
||||||
|
====
|
||||||
|
.text:008C12A1 mov ecx, eax
|
||||||
|
.text:008C12A3 nop
|
||||||
|
.text:008C12A4 nop
|
||||||
|
.text:008C12A5 nop
|
||||||
|
.text:008C12A6 nop
|
||||||
|
.text:008C12A7 nop
|
||||||
|
>>>>
|
||||||
|
|
||||||
|
|
||||||
|
basically:
|
||||||
|
|
||||||
|
b_squad_id = building->getSpecificSquad();
|
||||||
|
- if (b_squad_id != squad->id || !building->canUse(some_squad_id, 4))
|
||||||
|
+ if (b_squad_id != squad->id || !building->canUse(b_squad_id, 4))
|
||||||
|
unassign(building);
|
||||||
|
|
||||||
|
the reason being, some_other_squad_id contains irrelevant garbage at this point
|
||||||
|
|
||||||
|
|
||||||
|
---8<---
|
||||||
|
This difference file is created by The Interactive Disassembler
|
||||||
|
|
||||||
|
Dwarf Fortress.exe
|
||||||
|
004C05C4: 8B 89
|
||||||
|
004C05C5: 8C C1
|
||||||
|
004C05C6: 24 90
|
||||||
|
004C05C7: 80 90
|
||||||
|
004C05C8: 00 90
|
||||||
|
004C05C9: 00 90
|
||||||
|
004C05CA: 00 90
|
||||||
|
004C06A1: 8B 89
|
||||||
|
004C06A2: 8C C1
|
||||||
|
004C06A3: 24 90
|
||||||
|
004C06A4: 80 90
|
||||||
|
004C06A5: 00 90
|
||||||
|
004C06A6: 00 90
|
||||||
|
004C06A7: 00 90
|
@ -0,0 +1,147 @@
|
|||||||
|
http://www.bay12games.com/dwarves/mantisbt/view.php?id=1445
|
||||||
|
|
||||||
|
0x9461
|
||||||
|
90 90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||||
|
C7 44 24 18 01 00 00 00 FF A0 44 01 00 00
|
||||||
|
|
||||||
|
.text:08051461 sub_8051461 proc near
|
||||||
|
.text:08051461 mov dword ptr [esp+18h], 1
|
||||||
|
.text:08051469 jmp dword ptr [eax+144h]
|
||||||
|
.text:08051469 sub_8051461 endp
|
||||||
|
|
||||||
|
0x9548
|
||||||
|
90 90 90 90 90 90 90 90
|
||||||
|
FF 4C 24 14 78 08 EB 0B
|
||||||
|
|
||||||
|
.text:08051548 loc_8051548:
|
||||||
|
.text:08051548 dec dword ptr [esp+14h]
|
||||||
|
.text:0805154C js short loc_8051556
|
||||||
|
.text:0805154E jmp short loc_805155B
|
||||||
|
|
||||||
|
0x9556
|
||||||
|
90 90 90 90 90 90 90 90 90 90
|
||||||
|
E9 F6 8C 05 00 E9 D0 8D 05 00
|
||||||
|
|
||||||
|
.text:08051556 loc_8051556:
|
||||||
|
.text:08051556 jmp loc_80AA251
|
||||||
|
.text:0805155B loc_805155B:
|
||||||
|
.text:0805155B jmp loc_80AA330
|
||||||
|
|
||||||
|
0x9568
|
||||||
|
90 90 90 90 90 90 90 90
|
||||||
|
FF 4C 24 14 78 E8 EB 06
|
||||||
|
|
||||||
|
.text:08051568 loc_8051568:
|
||||||
|
.text:08051568 dec [esp+14h]
|
||||||
|
.text:0805156C js short loc_8051556
|
||||||
|
.text:0805156E jmp short loc_8051576
|
||||||
|
|
||||||
|
0x9576
|
||||||
|
90 90 90 90 90
|
||||||
|
E9 4D 8E 05 00
|
||||||
|
|
||||||
|
.text:08051576 loc_8051576:
|
||||||
|
.text:08051576 jmp loc_80AA3C8
|
||||||
|
|
||||||
|
0x62243
|
||||||
|
FF 90 44 01 00 00
|
||||||
|
E8 19 72 FA FF 90
|
||||||
|
|
||||||
|
<<<<
|
||||||
|
.text:080AA243 call dword ptr [eax+144h]
|
||||||
|
====
|
||||||
|
.text:080AA243 call sub_8051461
|
||||||
|
.text:080AA248 nop
|
||||||
|
>>>>
|
||||||
|
|
||||||
|
0x62369
|
||||||
|
E9 E3 FE FF FF
|
||||||
|
E9 DA 71 FA FF
|
||||||
|
|
||||||
|
<<<<
|
||||||
|
.text:080AA369 jmp loc_80AA251
|
||||||
|
====
|
||||||
|
.text:080AA369 jmp loc_8051548
|
||||||
|
>>>>
|
||||||
|
|
||||||
|
0x623f6
|
||||||
|
E9 56 FE FF FF
|
||||||
|
E9 6D 71 FA FF
|
||||||
|
|
||||||
|
<<<<
|
||||||
|
.text:080AA3F6 jmp loc_80AA251
|
||||||
|
====
|
||||||
|
.text:080AA3F6 jmp loc_8051568
|
||||||
|
>>>>
|
||||||
|
|
||||||
|
basically:
|
||||||
|
|
||||||
|
+ int allowed_count = 1; // to mean 2
|
||||||
|
...
|
||||||
|
- if (type(item) == new_type)
|
||||||
|
+ if (type(item) == new_type && --allowed_count < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
to allow up to two items of the same type at the same time
|
||||||
|
|
||||||
|
---8<---
|
||||||
|
This difference file is created by The Interactive Disassembler
|
||||||
|
|
||||||
|
Dwarf_Fortress
|
||||||
|
00009461: 90 C7
|
||||||
|
00009462: 90 44
|
||||||
|
00009463: 90 24
|
||||||
|
00009464: 90 18
|
||||||
|
00009465: 90 01
|
||||||
|
00009466: 90 00
|
||||||
|
00009467: 90 00
|
||||||
|
00009468: 90 00
|
||||||
|
00009469: 90 FF
|
||||||
|
0000946A: 90 A0
|
||||||
|
0000946B: 90 44
|
||||||
|
0000946C: 90 01
|
||||||
|
0000946D: 90 00
|
||||||
|
0000946E: 90 00
|
||||||
|
00009548: 90 FF
|
||||||
|
00009549: 90 4C
|
||||||
|
0000954A: 90 24
|
||||||
|
0000954B: 90 14
|
||||||
|
0000954C: 90 78
|
||||||
|
0000954D: 90 08
|
||||||
|
0000954E: 90 EB
|
||||||
|
0000954F: 90 0B
|
||||||
|
00009556: 90 E9
|
||||||
|
00009557: 90 F6
|
||||||
|
00009558: 90 8C
|
||||||
|
00009559: 90 05
|
||||||
|
0000955A: 90 00
|
||||||
|
0000955B: 90 E9
|
||||||
|
0000955C: 90 D0
|
||||||
|
0000955D: 90 8D
|
||||||
|
0000955E: 90 05
|
||||||
|
0000955F: 90 00
|
||||||
|
00009568: 90 FF
|
||||||
|
00009569: 90 4C
|
||||||
|
0000956A: 90 24
|
||||||
|
0000956B: 90 14
|
||||||
|
0000956C: 90 78
|
||||||
|
0000956D: 90 E8
|
||||||
|
0000956E: 90 EB
|
||||||
|
0000956F: 90 06
|
||||||
|
00009576: 90 E9
|
||||||
|
00009577: 90 4D
|
||||||
|
00009578: 90 8E
|
||||||
|
00009579: 90 05
|
||||||
|
0000957A: 90 00
|
||||||
|
00062243: FF E8
|
||||||
|
00062244: 90 19
|
||||||
|
00062245: 44 72
|
||||||
|
00062246: 01 FA
|
||||||
|
00062247: 00 FF
|
||||||
|
00062248: 00 90
|
||||||
|
0006236A: E3 DA
|
||||||
|
0006236B: FE 71
|
||||||
|
0006236C: FF FA
|
||||||
|
000623F7: 56 6D
|
||||||
|
000623F8: FE 71
|
||||||
|
000623F9: FF FA
|
@ -0,0 +1,40 @@
|
|||||||
|
http://www.bay12games.com/dwarves/mantisbt/view.php?id=808
|
||||||
|
|
||||||
|
for (i = 0; i < num_items; i++)
|
||||||
|
{
|
||||||
|
ridx = reagent_idx[i];
|
||||||
|
sz = reagent_quantity[ridx]; // used quantity
|
||||||
|
if (sz <= 0) continue;
|
||||||
|
reag = reagent[ridx];
|
||||||
|
if (reag->flags.PRESERVE_REAGENT) continue;
|
||||||
|
rsz = items[i]->getTotalDimension();
|
||||||
|
<<<<<<<<
|
||||||
|
if (reag->flags3.ANY_RAW_MATERIAL)
|
||||||
|
rsz *= BASE_SIZE(items[i]->getType());
|
||||||
|
if (items[i]->subtractDimension(rsz))
|
||||||
|
========
|
||||||
|
/* Not in patch, but necessary for full correctness:
|
||||||
|
if (reag->flags3.ANY_RAW_MATERIAL)
|
||||||
|
rsz /= BASE_SIZE(items[i]->getType());
|
||||||
|
*/
|
||||||
|
if (reag->flags3.ANY_RAW_MATERIAL)
|
||||||
|
sz *= BASE_SIZE(items[i]->getType());
|
||||||
|
if (items[i]->subtractDimension(sz))
|
||||||
|
>>>>>>>>
|
||||||
|
destroy_item(items[i]);
|
||||||
|
reagent_quantity[ridx] -= rsz
|
||||||
|
if (reagent_quantity[ridx] < 0)
|
||||||
|
reagent_quantity[ridx] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
You can use this script to apply the generated patch below:
|
||||||
|
http://stalkr.net/files/ida/idadif.py
|
||||||
|
|
||||||
|
----8<----
|
||||||
|
This difference file is created by The Interactive Disassembler
|
||||||
|
|
||||||
|
Dwarf_Fortress
|
||||||
|
0087F7EF: F8 D8
|
||||||
|
0087F86F: F8 D8
|
||||||
|
0087F9AD: C7 C3
|
||||||
|
0087F9ED: C7 C3
|
@ -0,0 +1,83 @@
|
|||||||
|
http://www.bay12games.com/dwarves/mantisbt/view.php?id=5994
|
||||||
|
|
||||||
|
Original code:
|
||||||
|
|
||||||
|
.text:087AC378 cmp edx, eax
|
||||||
|
.text:087AC37A mov [esp+4Ch], eax
|
||||||
|
.text:087AC37E jnb loc_87A7034
|
||||||
|
.text:087AC384 mov [esp+48h], edx
|
||||||
|
.text:087AC388 mov [esp+54h], ebx
|
||||||
|
...
|
||||||
|
.text:087AC440 add dword ptr [esp+48h], 4
|
||||||
|
.text:087AC445 mov ebp, [esp+48h]
|
||||||
|
.text:087AC449 cmp [esp+4Ch], ebp
|
||||||
|
.text:087AC44D ja loc_87AC38C
|
||||||
|
|
||||||
|
Patch:
|
||||||
|
|
||||||
|
0x76437a
|
||||||
|
89 44 24 4C
|
||||||
|
89 54 24 4C
|
||||||
|
|
||||||
|
.text:087AC37A mov [esp+4Ch], edx
|
||||||
|
|
||||||
|
0x764384
|
||||||
|
89 54 24 48 89 5C 24 54
|
||||||
|
E8 8A 51 8A FF 90 90 90
|
||||||
|
|
||||||
|
.text:087AC384 call sub_8051513
|
||||||
|
.text:087AC389 nop
|
||||||
|
.text:087AC38A nop
|
||||||
|
.text:087AC38B nop
|
||||||
|
|
||||||
|
0x764440
|
||||||
|
83 44 24 48 04 8B 6C 24 48 39 6C 24 4C 0F 87 39 FF FF FF
|
||||||
|
83 6C 24 48 04 8B 6C 24 48 39 6C 24 4C 0F 86 39 FF FF FF
|
||||||
|
|
||||||
|
.text:087AC440 sub dword ptr [esp+48h], 4
|
||||||
|
.text:087AC445 mov ebp, [esp+48h]
|
||||||
|
.text:087AC449 cmp [esp+4Ch], ebp
|
||||||
|
.text:087AC44D jbe loc_87AC38C
|
||||||
|
|
||||||
|
0x9513
|
||||||
|
90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||||
|
83 E8 04 89 44 24 4C 89 5C 24 58 C3 90
|
||||||
|
|
||||||
|
.text:08051513 sub_8051513 proc near
|
||||||
|
.text:08051513 sub eax, 4
|
||||||
|
.text:08051516 mov [esp+4Ch], eax ; 48h
|
||||||
|
.text:0805151A mov [esp+58h], ebx ; 54h
|
||||||
|
.text:0805151E retn
|
||||||
|
.text:0805151E sub_8051513 endp
|
||||||
|
|
||||||
|
|
||||||
|
You can use this script to apply the generated patch below:
|
||||||
|
http://stalkr.net/files/ida/idadif.py
|
||||||
|
|
||||||
|
----8<----
|
||||||
|
This difference file is created by The Interactive Disassembler
|
||||||
|
|
||||||
|
Dwarf_Fortress
|
||||||
|
00009513: 90 83
|
||||||
|
00009514: 90 E8
|
||||||
|
00009515: 90 04
|
||||||
|
00009516: 90 89
|
||||||
|
00009517: 90 44
|
||||||
|
00009518: 90 24
|
||||||
|
00009519: 90 4C
|
||||||
|
0000951A: 90 89
|
||||||
|
0000951B: 90 5C
|
||||||
|
0000951C: 90 24
|
||||||
|
0000951D: 90 58
|
||||||
|
0000951E: 90 C3
|
||||||
|
0076437B: 44 54
|
||||||
|
00764384: 89 E8
|
||||||
|
00764385: 54 8A
|
||||||
|
00764386: 24 51
|
||||||
|
00764387: 48 8A
|
||||||
|
00764388: 89 FF
|
||||||
|
00764389: 5C 90
|
||||||
|
0076438A: 24 90
|
||||||
|
0076438B: 54 90
|
||||||
|
00764441: 44 6C
|
||||||
|
0076444E: 87 86
|
@ -0,0 +1,139 @@
|
|||||||
|
http://www.bay12games.com/dwarves/mantisbt/view.php?id=5994
|
||||||
|
|
||||||
|
0x7643f8
|
||||||
|
F6 46 0C 01 74 42
|
||||||
|
E9 B6 50 8A FF 90
|
||||||
|
|
||||||
|
.text:087AC3F8 jmp loc_80514B3 ; << CAVE
|
||||||
|
.text:087AC3FD nop
|
||||||
|
.text:087AC3FE loc_87AC3FE:
|
||||||
|
|
||||||
|
0x94b3
|
||||||
|
90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||||
|
F6 46 0C 01 75 0A E9 82 AF 75 00 90 90
|
||||||
|
|
||||||
|
.text:080514B3 loc_80514B3:
|
||||||
|
.text:080514B3 test byte ptr [esi+0Ch], 1
|
||||||
|
.text:080514B7 jnz short loc_80514C3
|
||||||
|
.text:080514B9 coord_test_jfail:
|
||||||
|
.text:080514B9 jmp loc_87AC440
|
||||||
|
|
||||||
|
0x94c3
|
||||||
|
90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||||
|
8D 9C 24 60 03 00 00 0F BF 03 EB 07 90
|
||||||
|
|
||||||
|
.text:080514C3 loc_80514C3:
|
||||||
|
.text:080514C3 lea ebx, [esp+360h]
|
||||||
|
.text:080514CA movsx eax, word ptr [ebx] ; job_z
|
||||||
|
.text:080514CD jmp short loc_80514D6
|
||||||
|
|
||||||
|
0x94d6
|
||||||
|
90 90 90 90 90 90 90 90 90 90
|
||||||
|
66 3B 46 08 75 DD EB 05 90 90
|
||||||
|
|
||||||
|
.text:080514D6 loc_80514D6:
|
||||||
|
.text:080514D6 cmp ax, [esi+8] ; item->pos.z
|
||||||
|
.text:080514DA jnz short coord_test_jfail
|
||||||
|
.text:080514DC jmp short loc_80514E3
|
||||||
|
|
||||||
|
0x94e3
|
||||||
|
90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||||
|
0F BF 43 10 66 3B 46 04 75 CC EB 04 90
|
||||||
|
|
||||||
|
.text:080514E3 loc_80514E3:
|
||||||
|
.text:080514E3 movsx eax, word ptr [ebx+10h] ; job_x
|
||||||
|
.text:080514E7 cmp ax, [esi+4] ; item->pos.x
|
||||||
|
.text:080514EB jnz short coord_test_jfail
|
||||||
|
.text:080514ED jmp short loc_80514F3
|
||||||
|
|
||||||
|
0x94f3
|
||||||
|
90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||||
|
0F BF 43 20 66 3B 46 06 75 BC EB 04 90
|
||||||
|
|
||||||
|
.text:080514F3 loc_80514F3:
|
||||||
|
.text:080514F3 movsx eax, word ptr [ebx+20h] ; job_y
|
||||||
|
.text:080514F7 cmp ax, [esi+6] ; item->pos.y
|
||||||
|
.text:080514FB jnz short coord_test_jfail
|
||||||
|
.text:080514FD jmp short loc_8051503
|
||||||
|
|
||||||
|
0x9503
|
||||||
|
90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||||
|
E9 F6 AE 75 00 90 90 90 90 90 90 90 90
|
||||||
|
|
||||||
|
.text:08051503 loc_8051503:
|
||||||
|
.text:08051503 jmp loc_87AC3FE
|
||||||
|
|
||||||
|
|
||||||
|
You can use this script to apply the generated patch below:
|
||||||
|
http://stalkr.net/files/ida/idadif.py
|
||||||
|
|
||||||
|
----8<----
|
||||||
|
This difference file is created by The Interactive Disassembler
|
||||||
|
|
||||||
|
Dwarf_Fortress
|
||||||
|
000094B3: 90 F6
|
||||||
|
000094B4: 90 46
|
||||||
|
000094B5: 90 0C
|
||||||
|
000094B6: 90 01
|
||||||
|
000094B7: 90 75
|
||||||
|
000094B8: 90 0A
|
||||||
|
000094B9: 90 E9
|
||||||
|
000094BA: 90 82
|
||||||
|
000094BB: 90 AF
|
||||||
|
000094BC: 90 75
|
||||||
|
000094BD: 90 00
|
||||||
|
000094C3: 90 8D
|
||||||
|
000094C4: 90 9C
|
||||||
|
000094C5: 90 24
|
||||||
|
000094C6: 90 60
|
||||||
|
000094C7: 90 03
|
||||||
|
000094C8: 90 00
|
||||||
|
000094C9: 90 00
|
||||||
|
000094CA: 90 0F
|
||||||
|
000094CB: 90 BF
|
||||||
|
000094CC: 90 03
|
||||||
|
000094CD: 90 EB
|
||||||
|
000094CE: 90 07
|
||||||
|
000094D6: 90 66
|
||||||
|
000094D7: 90 3B
|
||||||
|
000094D8: 90 46
|
||||||
|
000094D9: 90 08
|
||||||
|
000094DA: 90 75
|
||||||
|
000094DB: 90 DD
|
||||||
|
000094DC: 90 EB
|
||||||
|
000094DD: 90 05
|
||||||
|
000094E3: 90 0F
|
||||||
|
000094E4: 90 BF
|
||||||
|
000094E5: 90 43
|
||||||
|
000094E6: 90 10
|
||||||
|
000094E7: 90 66
|
||||||
|
000094E8: 90 3B
|
||||||
|
000094E9: 90 46
|
||||||
|
000094EA: 90 04
|
||||||
|
000094EB: 90 75
|
||||||
|
000094EC: 90 CC
|
||||||
|
000094ED: 90 EB
|
||||||
|
000094EE: 90 04
|
||||||
|
000094F3: 90 0F
|
||||||
|
000094F4: 90 BF
|
||||||
|
000094F5: 90 43
|
||||||
|
000094F6: 90 20
|
||||||
|
000094F7: 90 66
|
||||||
|
000094F8: 90 3B
|
||||||
|
000094F9: 90 46
|
||||||
|
000094FA: 90 06
|
||||||
|
000094FB: 90 75
|
||||||
|
000094FC: 90 BC
|
||||||
|
000094FD: 90 EB
|
||||||
|
000094FE: 90 04
|
||||||
|
00009503: 90 E9
|
||||||
|
00009504: 90 F6
|
||||||
|
00009505: 90 AE
|
||||||
|
00009506: 90 75
|
||||||
|
00009507: 90 00
|
||||||
|
007643F8: F6 E9
|
||||||
|
007643F9: 46 B6
|
||||||
|
007643FA: 0C 50
|
||||||
|
007643FB: 01 8A
|
||||||
|
007643FC: 74 FF
|
||||||
|
007643FD: 42 90
|
@ -0,0 +1,60 @@
|
|||||||
|
http://www.bay12games.com/dwarves/mantisbt/view.php?id=4406
|
||||||
|
|
||||||
|
1. Include store in hospital jobs when recomputing counters
|
||||||
|
|
||||||
|
0x746d7
|
||||||
|
75 D7
|
||||||
|
90 90
|
||||||
|
|
||||||
|
<<<<
|
||||||
|
.text:080BC6D7 jnz short loc_80BC6B0
|
||||||
|
====
|
||||||
|
.text:080BC6D7 nop
|
||||||
|
.text:080BC6D8 nop
|
||||||
|
>>>>
|
||||||
|
|
||||||
|
- if (job->getBuildingRef(BUILDING_DESTINATION) != this) continue;
|
||||||
|
+ // NOP
|
||||||
|
|
||||||
|
This reference points to the containers, not the hospital civzone.
|
||||||
|
Since fixing this properly is too hard for a patch, just remove the
|
||||||
|
check. Most people have only one hospital anyway, and it is better
|
||||||
|
to err on the side of caution here.
|
||||||
|
|
||||||
|
|
||||||
|
2. Make the stockpiling code increment the right stock counters
|
||||||
|
|
||||||
|
0x67cb0e
|
||||||
|
0B 04 90
|
||||||
|
8B 1C 90
|
||||||
|
|
||||||
|
0x67cb18
|
||||||
|
8B 40 74
|
||||||
|
8B 43 74
|
||||||
|
|
||||||
|
<<<<
|
||||||
|
.text:086C4B0E mov eax, [eax+edx*4]
|
||||||
|
.text:086C4B11 mov edx, [esp+ecx*4+39Ch+var_2B4]
|
||||||
|
.text:086C4B18 mov eax, [eax+74h]
|
||||||
|
====
|
||||||
|
.text:086C4B0E mov ebx, [eax+edx*4]
|
||||||
|
.text:086C4B11 mov edx, [esp+ecx*4+39Ch+var_2B4]
|
||||||
|
.text:086C4B18 mov eax, [ebx+74h]
|
||||||
|
>>>>
|
||||||
|
|
||||||
|
- id = civzones[i]->children[child_idx[i]]->id
|
||||||
|
+ cur_civzone = civzones[i] // existing var from previous loop
|
||||||
|
+ id = cur_civzone->children[child_idx[i]]->id
|
||||||
|
|
||||||
|
The reason being, later code uses that var (at this point containing
|
||||||
|
useless data) to increment counters and amounts in the hospital.
|
||||||
|
|
||||||
|
|
||||||
|
---8<---
|
||||||
|
This difference file is created by The Interactive Disassembler
|
||||||
|
|
||||||
|
Dwarf_Fortress
|
||||||
|
000746D7: 75 90
|
||||||
|
000746D8: D7 90
|
||||||
|
0067CB0F: 04 1C
|
||||||
|
0067CB19: 40 43
|
@ -0,0 +1,85 @@
|
|||||||
|
http://www.bay12games.com/dwarves/mantisbt/view.php?id=4530
|
||||||
|
|
||||||
|
0x9508
|
||||||
|
|
||||||
|
90 90 90 90 90 90 90 90
|
||||||
|
E9 13 76 9C 00 90 90 90
|
||||||
|
|
||||||
|
.text:08051508 loc_8051508:
|
||||||
|
.text:08051508 jmp sub_8A18B20
|
||||||
|
|
||||||
|
0x9523
|
||||||
|
|
||||||
|
90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||||
|
50 8B 03 53 FF 90 34 02 00 00 EB 09 90
|
||||||
|
|
||||||
|
.text:08051523 sub_8051523:
|
||||||
|
.text:08051523 push eax
|
||||||
|
.text:08051524 mov eax, [ebx]
|
||||||
|
.text:08051526 push ebx
|
||||||
|
.text:08051527 call dword ptr [eax+234h]
|
||||||
|
.text:0805152D jmp short loc_8051538
|
||||||
|
|
||||||
|
0x9538
|
||||||
|
|
||||||
|
90 90 90 90 90 90 90 90
|
||||||
|
29 44 24 64 5B 58 EB C8
|
||||||
|
|
||||||
|
.text:08051538 loc_8051538:
|
||||||
|
.text:08051538 sub [esp+64h], eax
|
||||||
|
.text:0805153C pop ebx
|
||||||
|
.text:0805153D pop eax
|
||||||
|
.text:0805153E jmp short loc_8051508
|
||||||
|
|
||||||
|
0xa5cdd0
|
||||||
|
|
||||||
|
29 44 24 58
|
||||||
|
90 90 90 90
|
||||||
|
|
||||||
|
.text:08AA4DD0 nop
|
||||||
|
.text:08AA4DD1 nop
|
||||||
|
.text:08AA4DD2 nop
|
||||||
|
.text:08AA4DD3 nop
|
||||||
|
|
||||||
|
0xa5e2c3
|
||||||
|
|
||||||
|
E8 58 28 F7 FF
|
||||||
|
E8 5B B2 5A FF
|
||||||
|
|
||||||
|
.text:08AA62C3 call sub_8051523
|
||||||
|
|
||||||
|
---8<---
|
||||||
|
This difference file is created by The Interactive Disassembler
|
||||||
|
|
||||||
|
Dwarf_Fortress
|
||||||
|
00009508: 90 E9
|
||||||
|
00009509: 90 13
|
||||||
|
0000950A: 90 76
|
||||||
|
0000950B: 90 9C
|
||||||
|
0000950C: 90 00
|
||||||
|
00009523: 90 50
|
||||||
|
00009524: 90 8B
|
||||||
|
00009525: 90 03
|
||||||
|
00009526: 90 53
|
||||||
|
00009527: 90 FF
|
||||||
|
00009529: 90 34
|
||||||
|
0000952A: 90 02
|
||||||
|
0000952B: 90 00
|
||||||
|
0000952C: 90 00
|
||||||
|
0000952D: 90 EB
|
||||||
|
0000952E: 90 09
|
||||||
|
00009538: 90 29
|
||||||
|
00009539: 90 44
|
||||||
|
0000953A: 90 24
|
||||||
|
0000953B: 90 64
|
||||||
|
0000953C: 90 5B
|
||||||
|
0000953D: 90 58
|
||||||
|
0000953E: 90 EB
|
||||||
|
0000953F: 90 C8
|
||||||
|
00A5CDD0: 29 90
|
||||||
|
00A5CDD1: 44 90
|
||||||
|
00A5CDD2: 24 90
|
||||||
|
00A5CDD3: 58 90
|
||||||
|
00A5E2C4: 58 5B
|
||||||
|
00A5E2C5: 28 B2
|
||||||
|
00A5E2C6: F7 5A
|
@ -0,0 +1,45 @@
|
|||||||
|
http://www.bay12games.com/dwarves/mantisbt/view.php?id=1445
|
||||||
|
|
||||||
|
Fix use of uninitialized variables to stop auto-unassigning racks:
|
||||||
|
|
||||||
|
0x7ee948
|
||||||
|
8B 7C 24 3C
|
||||||
|
89 C7 90 90
|
||||||
|
|
||||||
|
.text:08836948 mov edi, eax
|
||||||
|
.text:0883694A nop
|
||||||
|
.text:0883694B nop
|
||||||
|
|
||||||
|
|
||||||
|
0x7eea2f
|
||||||
|
8B 7C 24 3C
|
||||||
|
89 C7 90 90
|
||||||
|
|
||||||
|
.text:08836A2F mov edi, eax
|
||||||
|
.text:08836A31 nop
|
||||||
|
.text:08836A32 nop
|
||||||
|
|
||||||
|
|
||||||
|
basically:
|
||||||
|
|
||||||
|
b_squad_id = building->getSpecificSquad();
|
||||||
|
- if (b_squad_id != squad->id || !building->canUse(some_squad_id, 4))
|
||||||
|
+ if (b_squad_id != squad->id || !building->canUse(b_squad_id, 4))
|
||||||
|
unassign(building);
|
||||||
|
|
||||||
|
the reason being, some_other_squad_id contains irrelevant garbage at this point
|
||||||
|
|
||||||
|
|
||||||
|
---8<---
|
||||||
|
This difference file is created by The Interactive Disassembler
|
||||||
|
|
||||||
|
Dwarf_Fortress
|
||||||
|
007EE948: 8B 89
|
||||||
|
007EE949: 7C C7
|
||||||
|
007EE94A: 24 90
|
||||||
|
007EE94B: 3C 90
|
||||||
|
007EEA2F: 8B 89
|
||||||
|
007EEA30: 7C C7
|
||||||
|
007EEA31: 24 90
|
||||||
|
007EEA32: 3C 90
|
||||||
|
|
@ -1,26 +0,0 @@
|
|||||||
#ifndef FUNCTIONCALL__H
|
|
||||||
#define FUNCTIONCALL__H
|
|
||||||
#include <vector>
|
|
||||||
using std::vector;
|
|
||||||
using std::size_t;
|
|
||||||
class FunctionCaller
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum callconv
|
|
||||||
{
|
|
||||||
STD_CALL, //__stdcall - all in stack
|
|
||||||
FAST_CALL, //__fastcall - as much in registers as fits
|
|
||||||
THIS_CALL, //__thiscall - eax ptr to this, rest in stack
|
|
||||||
CDECL_CALL //__cdecl - same as stdcall but no stack realign
|
|
||||||
};
|
|
||||||
|
|
||||||
FunctionCaller(size_t base):base_(base){};
|
|
||||||
|
|
||||||
int CallFunction(size_t func_ptr,callconv conv,const vector<int> &arguments);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int CallF(size_t count,callconv conv,void* f,const vector<int> &arguments);
|
|
||||||
size_t base_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //FUNCTIONCALL__H
|
|
@ -1,14 +0,0 @@
|
|||||||
#ifndef LUA_FUNCTIONCALL__H
|
|
||||||
#define LUA_FUNCTIONCALL__H
|
|
||||||
|
|
||||||
#include "luamain.h"
|
|
||||||
#include "functioncall.h"
|
|
||||||
|
|
||||||
namespace lua
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
void RegisterFunctionCall(lua::state &st);
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,13 +0,0 @@
|
|||||||
#ifndef LUA_OFFSETS_H
|
|
||||||
#define LUA_OFFSETS_H
|
|
||||||
#include "luamain.h"
|
|
||||||
|
|
||||||
namespace lua
|
|
||||||
{
|
|
||||||
|
|
||||||
void RegisterEngine(lua::state &st);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,12 +0,0 @@
|
|||||||
#ifndef LUA_VERSIONINFO_H
|
|
||||||
#define LUA_VERSIONINFO_H
|
|
||||||
#include "Core.h"
|
|
||||||
#include <VersionInfo.h>
|
|
||||||
#include "luamain.h"
|
|
||||||
namespace lua
|
|
||||||
{
|
|
||||||
|
|
||||||
void RegisterVersionInfo(lua::state &st);
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,133 +0,0 @@
|
|||||||
adv_tools= {}
|
|
||||||
adv_tools.menu=MakeMenu()
|
|
||||||
--TODO make every tool generic (work for both modes)
|
|
||||||
function adv_tools.reincarnate(swap_soul) --only for adventurer i guess
|
|
||||||
if swap_soul==nil then
|
|
||||||
swap_soul=true
|
|
||||||
end
|
|
||||||
local adv=df.global.world.units.active[0]
|
|
||||||
if adv.flags1.dead==false then
|
|
||||||
error("You are not dead (yet)!")
|
|
||||||
end
|
|
||||||
local hist_fig=getNemesis(adv).figure
|
|
||||||
if hist_fig==nil then
|
|
||||||
error("No historical figure for adventurer...")
|
|
||||||
end
|
|
||||||
local events=df.global.world.history.events
|
|
||||||
local trg_hist_fig
|
|
||||||
for i=#events-1,0,-1 do -- reverse search because almost always it will be last entry
|
|
||||||
if df.history_event_hist_figure_diedst:is_instance(events[i]) then
|
|
||||||
--print("is instance:"..i)
|
|
||||||
if events[i].hfid==hist_fig.id then
|
|
||||||
--print("Is same id:"..i)
|
|
||||||
trg_hist_fig=events[i].slayer
|
|
||||||
if trg_hist_fig then
|
|
||||||
trg_hist_fig=df.historical_figure.find(trg_hist_fig)
|
|
||||||
end
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if trg_hist_fig ==nil then
|
|
||||||
error("Slayer not found")
|
|
||||||
end
|
|
||||||
|
|
||||||
local trg_unit=trg_hist_fig.unit_id
|
|
||||||
if trg_unit==nil then
|
|
||||||
error("Unit id not found!")
|
|
||||||
end
|
|
||||||
local trg_unit_final=df.unit.find(trg_unit)
|
|
||||||
|
|
||||||
tools.change_adv(trg_unit_final)
|
|
||||||
if swap_soul then --actually add a soul...
|
|
||||||
t_soul=adv.status.current_soul
|
|
||||||
adv.status.current_soul=df.NULL
|
|
||||||
adv.status.souls:resize(0)
|
|
||||||
trg_unit_final.status.current_soul=t_soul
|
|
||||||
trg_unit_final.status.souls:insert(#trg_unit_final.status.souls,t_soul)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
adv_tools.menu:add("Reincarnate",adv_tools.reincarnate)
|
|
||||||
function adv_tools.ressurect()
|
|
||||||
|
|
||||||
v2=engine.peek(vector:getval(indx),ptr_Creature.hurt1)
|
|
||||||
for i=0,v2:size()-1 do
|
|
||||||
v2:setval(i,0)
|
|
||||||
end
|
|
||||||
v2=engine.peek(vector:getval(indx),ptr_Creature.hurt2)
|
|
||||||
v2.type=DWORD
|
|
||||||
for i=0,v2:size()-1 do
|
|
||||||
v2:setval(i,0)
|
|
||||||
end
|
|
||||||
engine.poke(vector:getval(indx),ptr_Creature.bloodlvl,60000) --give blood
|
|
||||||
engine.poke(vector:getval(indx),ptr_Creature.bleedlvl,0) --stop some bleeding...
|
|
||||||
local flg=engine.peek(vector:getval(indx),ptr_Creature.flags)
|
|
||||||
flg:set(1,false) --ALIVE
|
|
||||||
flg:set(39,false) -- leave body yet again
|
|
||||||
flg:set(37,false) -- something todo with wounds- lets you walk again.
|
|
||||||
flg:set(58,true) -- makes them able to breathe
|
|
||||||
flg:set(61,true) -- gives them sight
|
|
||||||
engine.poke(vector:getval(indx),ptr_Creature.flags,flg)
|
|
||||||
end
|
|
||||||
|
|
||||||
function adv_tools.wagonmode() --by rumrusher
|
|
||||||
--first three lines same as before (because we will need an offset of creature at location x,y,z)
|
|
||||||
myoff=offsets.getEx("AdvCreatureVec")
|
|
||||||
vector=engine.peek(myoff,ptr_vector)
|
|
||||||
indx=GetCreatureAtPos(getxyz())
|
|
||||||
--indx=0
|
|
||||||
--print(string.format("%x",vector:getval(indx)))
|
|
||||||
flg=engine.peek(vector:getval(indx),ptr_Creature.flags) --get flags
|
|
||||||
flg:set(1,false)
|
|
||||||
flg:set(74,false)
|
|
||||||
engine.poke(vector:getval(indx),ptr_Creature.flags,flg)
|
|
||||||
print("To stay normal press y, else hit Enter turn Wagon mode on.")
|
|
||||||
r=io.stdin:read() -- repeat for it too work... also creature will be dead.
|
|
||||||
if r== "y" then
|
|
||||||
flg=engine.peek(vector:getval(indx),ptr_Creature.flags)
|
|
||||||
flg:set(1,false)
|
|
||||||
engine.poke(vector:getval(indx),ptr_Creature.flags,flg)
|
|
||||||
else
|
|
||||||
flg=engine.peek(vector:getval(indx),ptr_Creature.flags)
|
|
||||||
flg:set(1,false)
|
|
||||||
flg:flip(74)
|
|
||||||
engine.poke(vector:getval(indx),ptr_Creature.flags,flg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function selectall()
|
|
||||||
local retvec={} --return vector (or a list)
|
|
||||||
myoff=offsets.getEx("AdvCreatureVec")
|
|
||||||
vector=engine.peek(myoff,ptr_vector) --standart start
|
|
||||||
for i=0,vector:size()-1 do --check all creatures
|
|
||||||
local off
|
|
||||||
off=vector:getval(i)
|
|
||||||
local flags=engine.peek(off,ptr_Creature.flags)
|
|
||||||
if flags:get(1)==true then --if dead ...
|
|
||||||
table.insert(retvec,off)--... add it to return vector
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return retvec --return the "return vector" :)
|
|
||||||
end
|
|
||||||
function adv_tools.hostilate()
|
|
||||||
vector=engine.peek(offsets.getEx("AdvCreatureVec"),ptr_vector)
|
|
||||||
id=GetCreatureAtPos(getxyz())
|
|
||||||
print(string.format("Vec:%d cr:%d",vector:size(),id))
|
|
||||||
off=vector:getval(id)
|
|
||||||
crciv=engine.peek(vector:getval(id),ptr_Creature.civ)
|
|
||||||
curciv=engine.peek(vector:getval(0),ptr_Creature.civ)
|
|
||||||
|
|
||||||
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,true)
|
|
||||||
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,false)
|
|
||||||
flg:set(19,false)
|
|
||||||
engine.poke(off,ptr_Creature.flags,flg)
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,3 +0,0 @@
|
|||||||
if not(FILE) then
|
|
||||||
adv_tools.menu:display()
|
|
||||||
end
|
|
@ -1,24 +0,0 @@
|
|||||||
ptr_building={}
|
|
||||||
ptr_building.RTI={off=0,rtype=DWORD}
|
|
||||||
ptr_building.xs={off=4,rtype=DWORD}
|
|
||||||
ptr_building.ys={off=6,rtype=DWORD}
|
|
||||||
ptr_building.zs={off=8,rtype=DWORD}
|
|
||||||
ptr_building.xe={off=12,rtype=DWORD}
|
|
||||||
ptr_building.ye={off=16,rtype=DWORD}
|
|
||||||
ptr_building.ze={off=20,rtype=DWORD}
|
|
||||||
ptr_building.flags={off=24,rtype=ptt_dfflag.new(4)}
|
|
||||||
ptr_building.materials={off=28,rtype=DWORD}
|
|
||||||
ptr_building.builditems={off=228,rtype=ptr_vector}
|
|
||||||
function ptr_building.getname(self,RTI)
|
|
||||||
if RTI == nil then
|
|
||||||
return string.sub(RTTI_GetName(self.RTI),5,-3)
|
|
||||||
else
|
|
||||||
return string.sub(RTTI_GetName(RTI),5,-3)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
ptr_subbuilding={}
|
|
||||||
ptr_subbuilding["building_trapst"]={}
|
|
||||||
ptr_subbuilding["building_trapst"].state={off=250,rtype=DWORD} -- atleast lever has this
|
|
||||||
ptr_subbuilding["building_doorst"]={}
|
|
||||||
ptr_subbuilding["building_doorst"].flg={off=248,rtype=WORD} --maybe flags?
|
|
||||||
ptr_subbuilding["building_doorst"].state={off=250,rtype=DWORD}
|
|
@ -1,548 +0,0 @@
|
|||||||
dofile("dfusion/offsets_misc.lua")
|
|
||||||
STD_STRING=0
|
|
||||||
DWORD=1
|
|
||||||
WORD=2
|
|
||||||
BYTE=3
|
|
||||||
QWORD=4
|
|
||||||
DOUBLE=5
|
|
||||||
FLOAT=6
|
|
||||||
|
|
||||||
getline=function (inp)
|
|
||||||
return dfhack.lineedit(inp or "")
|
|
||||||
end
|
|
||||||
io.stdin=nil
|
|
||||||
|
|
||||||
function printd(...)
|
|
||||||
if DEBUG then
|
|
||||||
print(...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function GetTextRegion()
|
|
||||||
if __TEXT ~=nil then --Chache this, not going to change.
|
|
||||||
return __TEXT
|
|
||||||
end
|
|
||||||
|
|
||||||
ranges__=Process.getMemRanges()
|
|
||||||
--print("Ranges:"..#ranges__)
|
|
||||||
for k,v in pairs(ranges__) do
|
|
||||||
for k2,v2 in pairs(v) do
|
|
||||||
--print(string.format("%d %s->%s",k,tostring(k2),tostring(v2)))
|
|
||||||
end
|
|
||||||
--local num
|
|
||||||
--flgs=""
|
|
||||||
--if(v["read"])then flgs=flgs..'r' end
|
|
||||||
--if(v["write"])then flgs=flgs..'w' end
|
|
||||||
--if(v["execute"]) then flgs=flgs..'e' end
|
|
||||||
--if num>=100 then
|
|
||||||
--print(string.format("%d %x->%x %s %s",k,v["start"],v["end"],v.name or "",flgs))
|
|
||||||
--end
|
|
||||||
local pos=string.find(v.name,"Dwarf Fortress.exe") or string.find(v.name,"libs/Dwarf_Fortress")
|
|
||||||
if(pos~=nil) and v["execute"] then
|
|
||||||
__TEXT=v;
|
|
||||||
return v;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
error(".Text region not found!")
|
|
||||||
end
|
|
||||||
function UpdateRanges()
|
|
||||||
ranges__=Process.getMemRanges()
|
|
||||||
end
|
|
||||||
function GetRegionIn(pos)
|
|
||||||
ranges__=ranges__ or Process.getMemRanges()
|
|
||||||
for k,v in pairs(ranges__) do
|
|
||||||
if pos>=v.start and pos<v["end"] then
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
function GetRegionIn2(pos)
|
|
||||||
ranges__=ranges__ or Process.getMemRanges()
|
|
||||||
local cr=nil
|
|
||||||
for k,v in pairs(ranges__) do
|
|
||||||
--for k2,v2 in pairs(v) do
|
|
||||||
-- print(string.format("%d %s->%s",k,tostring(k2),tostring(v2)))
|
|
||||||
--end
|
|
||||||
--local num
|
|
||||||
--num=0
|
|
||||||
--if(v["read"])then num=num+1 end
|
|
||||||
--if(v["write"])then num=num+10 end
|
|
||||||
--if(v["execute"]) then num=num+100 end
|
|
||||||
--print(string.format("%d %x->%x %s %x",k,v["start"],v["end"],v.name,pos))
|
|
||||||
if pos>=v.start then --This is a hack to counter .text region suddenly shrinking.
|
|
||||||
if cr~=nil then
|
|
||||||
if v.start < cr.start then -- find region that start is closest
|
|
||||||
cr=v
|
|
||||||
end
|
|
||||||
else
|
|
||||||
cr=v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return cr
|
|
||||||
end
|
|
||||||
function ValidOffset(pos)
|
|
||||||
ranges__=ranges__ or Process.getMemRanges()
|
|
||||||
return GetRegionIn(pos)~=nil
|
|
||||||
end
|
|
||||||
function unlockDF()
|
|
||||||
local reg=GetTextRegion()
|
|
||||||
reg["write"]=true
|
|
||||||
Process.setPermisions(reg,reg)
|
|
||||||
end
|
|
||||||
function lockDF()
|
|
||||||
local reg=GetTextRegion()
|
|
||||||
reg["write"]=false
|
|
||||||
Process.setPermisions(reg,reg)
|
|
||||||
end
|
|
||||||
function SetExecute(pos)
|
|
||||||
UpdateRanges()
|
|
||||||
local reg=GetRegionIn(pos)
|
|
||||||
reg.execute=true
|
|
||||||
reg["write"]=true
|
|
||||||
Process.setPermisions(reg,reg) -- TODO maybe make a page with only execute permisions or sth
|
|
||||||
end
|
|
||||||
-- engine bindings
|
|
||||||
engine=engine or {}
|
|
||||||
--[=[ use default peek/pokes for now
|
|
||||||
engine.peekd=Process.readDWord
|
|
||||||
engine.poked=Process.writeDWord
|
|
||||||
engine.peekb=Process.readByte
|
|
||||||
engine.pokeb=Process.writeByte
|
|
||||||
engine.peekw=Process.readWord
|
|
||||||
engine.pokew=Process.writeWord
|
|
||||||
engine.peekstr_stl=Process.readSTLString
|
|
||||||
engine.pokestr_stl=Process.writeSTLString
|
|
||||||
engine.peekstr=Process.readCString
|
|
||||||
--engine.pokestr=Process.readCString
|
|
||||||
engine.peekarb=Process.read
|
|
||||||
engine.pokearb=Process.write
|
|
||||||
--]=]
|
|
||||||
|
|
||||||
function engine.peek(offset,rtype)
|
|
||||||
if type(rtype)=="table" then
|
|
||||||
if rtype.off ==nil then
|
|
||||||
return engine.peekpattern(offset,rtype)
|
|
||||||
else
|
|
||||||
return engine.peek(rtype.off+offset,rtype.rtype)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if rtype==STD_STRING then
|
|
||||||
return engine.peekstr2(offset)
|
|
||||||
elseif rtype==DWORD then
|
|
||||||
return engine.peekd(offset)
|
|
||||||
elseif rtype==WORD then
|
|
||||||
return engine.peekw(offset)
|
|
||||||
elseif rtype==BYTE then
|
|
||||||
return engine.peekb(offset)
|
|
||||||
elseif rtype==QWORD then
|
|
||||||
return engine.peekq(offset)
|
|
||||||
elseif rtype==FLOAT then
|
|
||||||
return engine.peekfloat(offset)
|
|
||||||
elseif rtype==DOUBLE then
|
|
||||||
return engine.peekdouble(offset)
|
|
||||||
else
|
|
||||||
error("Invalid peek type")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function engine.poke(offset,rtype,val)
|
|
||||||
if type(rtype)=="table" then
|
|
||||||
if rtype.off ==nil then
|
|
||||||
return engine.pokepattern(offset,rtype,val)
|
|
||||||
else
|
|
||||||
return engine.poke(rtype.off+offset,rtype.rtype,val)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if rtype==STD_STRING then
|
|
||||||
return engine.pokestr2(offset,val)
|
|
||||||
elseif rtype==DWORD then
|
|
||||||
return engine.poked(offset,val)
|
|
||||||
elseif rtype==WORD then
|
|
||||||
return engine.pokew(offset,val)
|
|
||||||
elseif rtype==BYTE then
|
|
||||||
return engine.pokeb(offset,val)
|
|
||||||
elseif rtype==QWORD then
|
|
||||||
return engine.pokeq(offset,val)
|
|
||||||
elseif rtype==FLOAT then
|
|
||||||
return engine.pokefloat(offset,val)
|
|
||||||
elseif rtype==DOUBLE then
|
|
||||||
return engine.pokedouble(offset,val)
|
|
||||||
else
|
|
||||||
error("Invalid poke type:"..tostring(rtype))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function engine.sizeof(rtype)
|
|
||||||
if rtype==STD_STRING then
|
|
||||||
error("String has no constant size")
|
|
||||||
return
|
|
||||||
elseif rtype==DWORD then
|
|
||||||
return 4;
|
|
||||||
elseif rtype==WORD then
|
|
||||||
return 2;
|
|
||||||
elseif rtype==BYTE then
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
error("Invalid sizeof type")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function engine.peekpattern(offset,pattern)
|
|
||||||
local ret={}
|
|
||||||
for k,v in pairs(pattern) do
|
|
||||||
--print("k:"..k.." v:"..type(v))
|
|
||||||
if type(v)=="table" then
|
|
||||||
ret[k]=engine.peek(offset+v.off,v.rtype)
|
|
||||||
--print(k.." peeked:"..offset+v.off)
|
|
||||||
else
|
|
||||||
ret[k]=v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
ret.__offset=offset
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
function engine.pokepattern(offset,pattern,val)
|
|
||||||
for k,v in pairs(pattern) do
|
|
||||||
--print("k:"..k.." v:"..type(v))
|
|
||||||
if type(v)=="table" then
|
|
||||||
engine.poke(offset+v.off,v.rtype,val[k])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function engine.LoadModData(file)
|
|
||||||
local T2={}
|
|
||||||
T2.symbols={}
|
|
||||||
T2.data,T2.size=engine.loadobj(file)
|
|
||||||
data,modsize=engine.loadobj(file)
|
|
||||||
local T=engine.loadobjsymbols(file)
|
|
||||||
for k,v in pairs(T) do
|
|
||||||
|
|
||||||
if v.pos~=0 then
|
|
||||||
T2.symbols[v.name]=v.pos
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return T2
|
|
||||||
end
|
|
||||||
function engine.FindMarkerCall(moddata,name)
|
|
||||||
if moddata.symbols[name] ~=nil then
|
|
||||||
return moddata.symbols[name]+1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function engine.FindMarker(moddata,name)
|
|
||||||
if moddata.symbols[name] ~=nil then
|
|
||||||
return engine.findmarker(0xDEADBEEF,moddata.data,moddata.size,moddata.symbols[name])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function engine.installMod(file,name,bonussize)
|
|
||||||
local T=engine.LoadModData(file)
|
|
||||||
local modpos,modsize=engine.loadmod(file,name,bonussize)
|
|
||||||
T.pos=modpos
|
|
||||||
return T
|
|
||||||
end
|
|
||||||
|
|
||||||
it_menu={}
|
|
||||||
it_menu.__index=it_menu
|
|
||||||
function it_menu:add(name,func)
|
|
||||||
table.insert(self.items,{func,name})
|
|
||||||
end
|
|
||||||
function it_menu:display()
|
|
||||||
print("Select choice (q exits):")
|
|
||||||
for p,c in pairs(self.items) do
|
|
||||||
print(string.format("%3d).%s",p,c[2]))
|
|
||||||
end
|
|
||||||
local ans
|
|
||||||
repeat
|
|
||||||
local r
|
|
||||||
r=getline("")
|
|
||||||
if r==nil then return end
|
|
||||||
if r=='q' then return end
|
|
||||||
ans=tonumber(r)
|
|
||||||
|
|
||||||
if ans==nil or not(ans<=#self.items and ans>0) then
|
|
||||||
print("incorrect choice")
|
|
||||||
end
|
|
||||||
|
|
||||||
until ans~=nil and (ans<=#self.items and ans>0)
|
|
||||||
self.items[ans][1]()
|
|
||||||
end
|
|
||||||
function MakeMenu()
|
|
||||||
local ret={}
|
|
||||||
ret.items={}
|
|
||||||
setmetatable(ret,it_menu)
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
function PrintPattern(loadedpattern)
|
|
||||||
for k,v in pairs(loadedpattern) do
|
|
||||||
if type(v)== "string" then
|
|
||||||
print(k.." "..v)
|
|
||||||
else
|
|
||||||
print(string.format("%s %d inhex:%x",k,v,v))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function printPattern(pattern)
|
|
||||||
local i=0;
|
|
||||||
local names={}
|
|
||||||
names[STD_STRING]="std_string (STD_STRING)"
|
|
||||||
names[DWORD]= "Double word (DWORD)"
|
|
||||||
names[WORD]= "Word (WORD)"
|
|
||||||
names[STD_STRING]="Byte (BYTE)"
|
|
||||||
ret={}
|
|
||||||
for k,v in pairs(pattern) do
|
|
||||||
if type(v)=="table" and v.off~=nil then
|
|
||||||
|
|
||||||
if names[v.rtype]~=nil then
|
|
||||||
lname=names[v.rtype]
|
|
||||||
else
|
|
||||||
if type(v.rtype)=="table" then
|
|
||||||
lname="Table (prob subpattern)"
|
|
||||||
else
|
|
||||||
lname="Other"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
print(string.format("%d. %s is %s with offset %x",i,k,lname,v.off))
|
|
||||||
table.insert(ret,k)
|
|
||||||
else
|
|
||||||
print(string.format("%d. %s",i,k))
|
|
||||||
end
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
return ret;
|
|
||||||
end
|
|
||||||
function editPattern(offset,pattern,name)
|
|
||||||
if type(pattern[name].rtype)=="table" then
|
|
||||||
if pattern[name].rtype.setval~=nil then
|
|
||||||
print(string.format("%x",offset+pattern[name].off))
|
|
||||||
local t=engine.peek(offset+pattern[name].off,pattern[name].rtype)
|
|
||||||
print("Value is now:"..t:getval())
|
|
||||||
print("Enter new value:")
|
|
||||||
val=io.stdin:read()
|
|
||||||
t:setval(val)
|
|
||||||
else
|
|
||||||
ModPattern(offset+pattern[name].off,pattern[name].rtype)
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
val=engine.peek(offset,pattern[name])
|
|
||||||
print("Value is now:"..val)
|
|
||||||
print("Enter new value:")
|
|
||||||
if pattern[name].rtype==STD_STRING then
|
|
||||||
val=io.stdin:read()
|
|
||||||
else
|
|
||||||
val=tonumber(io.stdin:read())
|
|
||||||
end
|
|
||||||
engine.poke(offset,pattern[name],val)
|
|
||||||
end
|
|
||||||
function ModPattern(itemoffset,pattern)
|
|
||||||
print("Select what to edit:")
|
|
||||||
nm=printPattern(pattern)
|
|
||||||
q=tonumber(io.stdin:read())
|
|
||||||
if q~=nil and q<#nm then
|
|
||||||
editPattern(itemoffset,pattern,nm[q+1])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function findVectors()
|
|
||||||
if __VECTORS ~=nil then --chache
|
|
||||||
return __VECTORS
|
|
||||||
end
|
|
||||||
local text=GetTextRegion()
|
|
||||||
local h=hexsearch(text.start,text["end"],0x8b,ANYBYTE,ANYDWORD,0x8b,ANYBYTE,ANYDWORD,0x2b)
|
|
||||||
local pos=h:findall()
|
|
||||||
local T={}
|
|
||||||
for k,v in pairs(pos) do
|
|
||||||
local loc1,loc2
|
|
||||||
loc1=engine.peekd(v+2)
|
|
||||||
loc2=engine.peekd(v+8)
|
|
||||||
--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
|
|
||||||
else
|
|
||||||
T[loc1-4]=1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
__VECTORS=T
|
|
||||||
return T
|
|
||||||
end
|
|
||||||
|
|
||||||
function GetRaceToken(p) --actually gets token...
|
|
||||||
local vec=df.global.world.raws.creatures.all
|
|
||||||
return vec[p].creature_id
|
|
||||||
end
|
|
||||||
function BuildNameTable()
|
|
||||||
local rtbl={}
|
|
||||||
local vec=df.global.world.raws.creatures.all
|
|
||||||
--print(string.format("Vector start:%x",vec.st))
|
|
||||||
--print(string.format("Vector end:%x",vec.en))
|
|
||||||
--print("Creature count:"..vec.size)
|
|
||||||
for k=0,#vec-1 do
|
|
||||||
local name=vec[k].creature_id
|
|
||||||
--print(k.." "..tostring(name))
|
|
||||||
rtbl[name]=k
|
|
||||||
end
|
|
||||||
return rtbl;
|
|
||||||
end
|
|
||||||
function BuildMaterialTable()
|
|
||||||
local rtbl={}
|
|
||||||
local vec=engine.peek(offsets.getEx('Materials'),ptr_vector)
|
|
||||||
--print(string.format("Vector start:%x",vec.st))
|
|
||||||
--print(string.format("Vector end:%x",vec.en))
|
|
||||||
--local i=0
|
|
||||||
for p=0,vec:size()-1 do
|
|
||||||
local off=vec:getval(p)
|
|
||||||
--print("First member:"..off)
|
|
||||||
local name=engine.peek(off,ptt_dfstring)
|
|
||||||
--print("Loading:"..p.."="..name:getval())
|
|
||||||
rtbl[name:getval()]=p
|
|
||||||
--i=i+1
|
|
||||||
--if i>100 then
|
|
||||||
-- io.stdin:read()
|
|
||||||
-- i=0
|
|
||||||
--end
|
|
||||||
end
|
|
||||||
return rtbl;
|
|
||||||
end
|
|
||||||
function BuildWordTables()
|
|
||||||
local names={}
|
|
||||||
local rnames={}
|
|
||||||
local vector=engine.peek(offsets.getEx('WordVec'),ptr_vector)
|
|
||||||
for i =0,vector:size()-1 do
|
|
||||||
local off=vector:getval(i)
|
|
||||||
local n=engine.peekstr(off)
|
|
||||||
names[i]=n
|
|
||||||
rnames[n]=i
|
|
||||||
end
|
|
||||||
return names,rnames
|
|
||||||
end
|
|
||||||
function ParseScript(file)
|
|
||||||
|
|
||||||
io.input(file)
|
|
||||||
f=""
|
|
||||||
first=0
|
|
||||||
nobraces=0
|
|
||||||
function updFunction()
|
|
||||||
if f~="" then
|
|
||||||
first=0
|
|
||||||
if nobraces==0 then
|
|
||||||
f=f.."}"
|
|
||||||
end
|
|
||||||
nobraces=0
|
|
||||||
print("Doing:"..f)
|
|
||||||
assert(loadstring(f))()
|
|
||||||
|
|
||||||
f=""
|
|
||||||
end
|
|
||||||
end
|
|
||||||
while true do
|
|
||||||
|
|
||||||
local line = io.read("*line")
|
|
||||||
if line == nil then break end
|
|
||||||
if string.sub(line,1,2)==">>" then
|
|
||||||
updFunction()
|
|
||||||
if string.find(line,"%b()") then
|
|
||||||
f=string.sub(line,3)
|
|
||||||
nobraces=1
|
|
||||||
else
|
|
||||||
f=string.sub(line,3).."{"
|
|
||||||
end
|
|
||||||
--print(string.sub(line,3)..)
|
|
||||||
else
|
|
||||||
if first~=0 then
|
|
||||||
f=f..","
|
|
||||||
else
|
|
||||||
first=1
|
|
||||||
end
|
|
||||||
f=f..string.format('%q',line)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
updFunction()
|
|
||||||
end
|
|
||||||
function ParseNames(path)
|
|
||||||
local ret={}
|
|
||||||
local ff=io.open(path)
|
|
||||||
for n in ff:lines() do
|
|
||||||
table.insert(ret,n)
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
function getSelectedUnit()
|
|
||||||
if df.global.ui.main.mode~=23 then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
local unit_indx=df.global.ui_selected_unit
|
|
||||||
if unit_indx<#df.global.world.units.active-1 then
|
|
||||||
return df.global.world.units.active[unit_indx]
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function getxyz() -- this will return pointers x,y and z coordinates.
|
|
||||||
local x=df.global.cursor.x
|
|
||||||
local y=df.global.cursor.y
|
|
||||||
local z=df.global.cursor.z
|
|
||||||
return x,y,z -- return the coords
|
|
||||||
end
|
|
||||||
function getCreatureAtPos(x,y,z) -- gets the creature index @ x,y,z coord
|
|
||||||
--local x,y,z=getxyz() --get 'X' coords
|
|
||||||
local vector=df.global.world.units.all -- load all creatures
|
|
||||||
for i = 0, #vector-1 do -- look into all creatures offsets
|
|
||||||
local curpos=vector[i].pos --get its coordinates
|
|
||||||
local cx=curpos.x
|
|
||||||
local cy=curpos.y
|
|
||||||
local cz=curpos.z
|
|
||||||
if cx==x and cy==y and cz==z then --compare them
|
|
||||||
return vector[i] --return index
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--print("Creature not found!")
|
|
||||||
return nil
|
|
||||||
|
|
||||||
end
|
|
||||||
function getCreatureAtPointer()
|
|
||||||
return getCreatureAtPos(getxyz())
|
|
||||||
end
|
|
||||||
function getCreature()
|
|
||||||
local unit=getSelectedUnit()
|
|
||||||
if unit==nil then
|
|
||||||
unit=getCreatureAtPointer()
|
|
||||||
end
|
|
||||||
--any other selection methods...
|
|
||||||
return unit
|
|
||||||
end
|
|
||||||
function getNemesisId(unit)
|
|
||||||
for k,v in pairs(unit.refs) do
|
|
||||||
if df.general_ref_is_nemesisst:is_instance(v) then
|
|
||||||
return v.nemesis_id
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function getNemesis(unit)
|
|
||||||
local id=getNemesisId(unit)
|
|
||||||
if id then
|
|
||||||
return df.nemesis_record.find(id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function Allocate(size)
|
|
||||||
local ptr=engine.getmod('General_Space')
|
|
||||||
if ptr==nil then
|
|
||||||
ptr=engine.newmod("General_Space",4096) -- some time later maybe make some more space
|
|
||||||
engine.poked(ptr,4)
|
|
||||||
end
|
|
||||||
|
|
||||||
local curptr=engine.peekd(ptr)
|
|
||||||
curptr=curptr+size
|
|
||||||
engine.poked(ptr,curptr)
|
|
||||||
return curptr-size+ptr
|
|
||||||
end
|
|
||||||
dofile("dfusion/patterns.lua")
|
|
||||||
dofile("dfusion/patterns2.lua")
|
|
||||||
dofile("dfusion/itempatterns.lua")
|
|
||||||
dofile("dfusion/buildingpatterns.lua")
|
|
@ -1,150 +0,0 @@
|
|||||||
function getTypename(object)
|
|
||||||
local tbl
|
|
||||||
local ret={}
|
|
||||||
if getmetatable(object)~=nil then
|
|
||||||
local tbl=getmetatable(object)
|
|
||||||
for k,v in pairs(xtypes) do
|
|
||||||
if v==tbl then
|
|
||||||
return k
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for k,v in pairs(xtypes.containers) do
|
|
||||||
if v==tbl then
|
|
||||||
return k
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if object.name~= nil then
|
|
||||||
return object.name
|
|
||||||
end
|
|
||||||
return "?"
|
|
||||||
end
|
|
||||||
function getFields(object)
|
|
||||||
local tbl
|
|
||||||
local ret={}
|
|
||||||
if getmetatable(object)==xtypes["struct-type"].wrap then
|
|
||||||
tbl=rawget(object,"mtype")
|
|
||||||
elseif getmetatable(object)==xtypes["struct-type"] then
|
|
||||||
tbl=object
|
|
||||||
else
|
|
||||||
error("Not an class_type or a class_object")
|
|
||||||
end
|
|
||||||
for k,v in pairs(tbl.types) do
|
|
||||||
table.insert(ret,{k,v[2],getTypename(v[1])})
|
|
||||||
--ret[v[2]]=k
|
|
||||||
--print(string.format("%s %x",k,v[2]))
|
|
||||||
end
|
|
||||||
table.sort(ret,function (a,b) return a[2]>b[2] end)
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
function editField(tbl,field,typename)
|
|
||||||
if EditType[typename] ~= nil then
|
|
||||||
EditType[typename](tbl[field])
|
|
||||||
else
|
|
||||||
print("Cur value:"..tostring(tbl[field]))
|
|
||||||
val=getline("Enter newvalue:")
|
|
||||||
tbl[field]=val
|
|
||||||
end
|
|
||||||
end
|
|
||||||
EditType={}
|
|
||||||
EditType["df-flagarray"]=function(trg)
|
|
||||||
local fields=rawget(trg,"mtype").index.names
|
|
||||||
print("Flag count:"..trg.size)
|
|
||||||
print("Name count:"..#fields)
|
|
||||||
for i=0,#fields do
|
|
||||||
print(string.format("%3d %20s %s",i,fields[i],tostring(trg[i-1])))
|
|
||||||
end
|
|
||||||
number=getline("enter flag id to flip:")
|
|
||||||
number=tonumber(number)
|
|
||||||
if number then
|
|
||||||
trg[fields[number]]= not trg[fields[number]]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
EditType["enum-type"]=function(trg)
|
|
||||||
local fields=rawget(trg,"mtype").names
|
|
||||||
local typename=getTypename(rawget(trg,"mtype").etype)
|
|
||||||
for k,v in pairs(fields) do
|
|
||||||
print(string.format("%3d %s",k,v))
|
|
||||||
end
|
|
||||||
local cval=trg:get()
|
|
||||||
if fields[cval]~= nil then
|
|
||||||
print(string.format("Current value:%d (%s)",cval,fields[cval]))
|
|
||||||
else
|
|
||||||
print(string.format("Current value:%d",cval))
|
|
||||||
end
|
|
||||||
number=getline("enter new value:")
|
|
||||||
number=tonumber(number)
|
|
||||||
if number then
|
|
||||||
trg:set(number)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
EditType["static-array"]=function(trg)
|
|
||||||
local item_type=rawget(trg,"mtype").item_type
|
|
||||||
local typename=getTypename(item_type)
|
|
||||||
number=getline(string.format("Select item (max %d, item-type '%s'):",trg.size,typename))
|
|
||||||
number=tonumber(number)
|
|
||||||
if number then
|
|
||||||
EditType[typename](trg[number])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
EditType["stl-vector"]=EditType["static-array"]
|
|
||||||
EditType["df-array"]=EditType["static-array"]
|
|
||||||
EditType["struct-type"]=function(trg)
|
|
||||||
local mtype=rawget(trg,"mtype")
|
|
||||||
local fields=getFields(trg)
|
|
||||||
for k,v in pairs(fields) do
|
|
||||||
print(string.format("%4d %25s %s",k,v[1],v[3]))
|
|
||||||
end
|
|
||||||
number=getline("Choose field to edit:")
|
|
||||||
number=tonumber(number)
|
|
||||||
if number then
|
|
||||||
local v=fields[number]
|
|
||||||
editField(trg,v[1],v[3])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
EditType["pointer"]=function(trg)
|
|
||||||
local mtype=rawget(trg,"mtype").ptype
|
|
||||||
local typename=getTypename(mtype)
|
|
||||||
if(trg:tonumber()==0) then
|
|
||||||
print("pointer points to nowhere!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
print("Auto dereferencing pointer! type:"..typename)
|
|
||||||
if EditType[typename] ~= nil then
|
|
||||||
EditType[typename](trg:deref())
|
|
||||||
else
|
|
||||||
print("Cur value:"..tostring(trg:deref()))
|
|
||||||
val=getline("Enter newvalue:")
|
|
||||||
trg:setref(val)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function EditDF()
|
|
||||||
local i=1
|
|
||||||
local tbl={}
|
|
||||||
for k,v in pairs(rawget(df,"types")) do
|
|
||||||
print(string.format("%4d %25s %s",i,k,getTypename(v)))
|
|
||||||
tbl[i]={k,getTypename(v)}
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
number=dfhack.lineedit("select item to edit (q to quit):")
|
|
||||||
if number and tonumber(number) then
|
|
||||||
local entry=tbl[tonumber(number)]
|
|
||||||
if entry==nil then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
editField(df,entry[1],entry[2])
|
|
||||||
--[=[
|
|
||||||
if EditType[entry[2]] ~= nil then
|
|
||||||
EditType[entry[2]](df[entry[1]])
|
|
||||||
else
|
|
||||||
print("Cur value:"..tostring(df[entry[1]]))
|
|
||||||
val=getline("Enter newvalue:")
|
|
||||||
df[entry[1]]=val
|
|
||||||
end
|
|
||||||
--]=]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function EditObject(obj)
|
|
||||||
EditType[getTypename(obj)](obj)
|
|
||||||
end
|
|
@ -1 +0,0 @@
|
|||||||
as -a --32 -o embark.o embark.asm
|
|
@ -1,83 +0,0 @@
|
|||||||
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
|
|
||||||
--print("adding:"..line.." id:"..RaceTable[line])
|
|
||||||
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=VersionInfo.getAddress('start_dwarf_count')
|
|
||||||
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=df.sizeof(df.global.ui:_field("race_id"))
|
|
||||||
|
|
||||||
loc=offsets.find(stoff,0x0f,0xb7,0x0d,DWORD_,tofind) --MOVZX ECX,WORD PTR[]
|
|
||||||
|
|
||||||
print(string.format("found:%x",loc))
|
|
||||||
if((loc~=0)and(loc-stoff<1000)) then
|
|
||||||
loc2=offsets.find(loc,0x83,0xc8,0xff) -- or eax, ffffff (for caste)
|
|
||||||
if loc2== 0 then
|
|
||||||
error ("Location for caste nulling not found!")
|
|
||||||
end
|
|
||||||
engine.pokeb(loc2,0x90)
|
|
||||||
engine.pokeb(loc2+1,0x90)
|
|
||||||
engine.pokeb(loc2+2,0x90)
|
|
||||||
ModData=engine.installMod("dfusion/embark/embark.o","Embark",256)
|
|
||||||
modpos=ModData.pos
|
|
||||||
modsize=ModData.size
|
|
||||||
local castepos=modpos+engine.FindMarker(ModData,"caste")
|
|
||||||
local racepos=modpos+engine.FindMarker(ModData,"race")
|
|
||||||
count=MakeTable(modpos,modsize,names)
|
|
||||||
engine.poked(castepos,modpos+modsize) --fix array start for race
|
|
||||||
engine.poked(racepos,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,0x90)
|
|
||||||
engine.pokeb(loc+1,0x90)
|
|
||||||
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,5 +0,0 @@
|
|||||||
|
|
||||||
if not(FILE)then
|
|
||||||
names=ParseNames("dfusion/embark/races.txt")--io.open("plugins/embark/races.txt"):lines()
|
|
||||||
embark(names)
|
|
||||||
end
|
|
@ -1,9 +0,0 @@
|
|||||||
ANT_MAN:0
|
|
||||||
ANT_MAN:0
|
|
||||||
ANT_MAN:0
|
|
||||||
ANT_MAN:1
|
|
||||||
ANT_MAN:1
|
|
||||||
ANT_MAN:0
|
|
||||||
ANT_MAN:0
|
|
||||||
ANT_MAN:2
|
|
||||||
ANT_MAN:3
|
|
Binary file not shown.
@ -1,45 +0,0 @@
|
|||||||
function analyzeF(off)
|
|
||||||
pos=offsets.find(off,0x39,ANYBYTE,0x8c,00,00,00)
|
|
||||||
print(string.format("Compare at:%x",pos))
|
|
||||||
if pos ==0 then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
if(pos-off>0x100) then
|
|
||||||
print(string.format("Distance to cmp:%x",pos-off))
|
|
||||||
pos =offsets.find(off,CALL)
|
|
||||||
print(string.format("Distance to call:%x",pos-off))
|
|
||||||
return 0
|
|
||||||
--return analyzeF(pos)
|
|
||||||
else
|
|
||||||
return pos
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function minEx(list)
|
|
||||||
local imin=list[1]
|
|
||||||
for _,v in ipairs(list) do
|
|
||||||
if imin> v and v~=0 then
|
|
||||||
imin=v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return imin
|
|
||||||
end
|
|
||||||
function signDword(dw)
|
|
||||||
if(dw>0xFFFFFFFF) then
|
|
||||||
return dw-0xFFFFFFFF
|
|
||||||
end
|
|
||||||
return dw
|
|
||||||
end
|
|
||||||
--[[
|
|
||||||
Warning: not all mov's are acounted for. Found one: mov EAX,WORD PTR[EBP+1EF4] WTF??
|
|
||||||
Two more compares are missing. There are calls instead (same function)
|
|
||||||
]]--
|
|
||||||
|
|
||||||
friendship_in={}
|
|
||||||
dofile("dfusion/friendship/install.lua")
|
|
||||||
dofile("dfusion/friendship/patch.lua")
|
|
||||||
|
|
||||||
function friendship(names)
|
|
||||||
friendship_in.install(names)
|
|
||||||
friendship_in.patch()
|
|
||||||
end
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
|||||||
|
|
||||||
function friendship_in.install(names)
|
|
||||||
RaceTable=RaceTable or BuildNameTable()
|
|
||||||
mypos=engine.getmod("Friendship")
|
|
||||||
if mypos then
|
|
||||||
modpos=mypos
|
|
||||||
_,modsize=engine.loadobj("dfusion/friendship/friendship.o")
|
|
||||||
_=nil
|
|
||||||
else
|
|
||||||
modpos,modsize=engine.loadmod("dfusion/friendship/friendship.o","Friendship",1024)
|
|
||||||
print(string.format("Loaded module @:%x",modpos))
|
|
||||||
end
|
|
||||||
count=0
|
|
||||||
for _,v in pairs(names) do
|
|
||||||
if RaceTable[v] == nil then
|
|
||||||
--print("Failure, "..v.." not found!")
|
|
||||||
error("Failure, "..v.." not found!")
|
|
||||||
--break --maybe some indication of failure? and cleanup?
|
|
||||||
end
|
|
||||||
engine.pokew(modpos+modsize+count*2+4+2,RaceTable[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(modpos+0x8f,modpos+modsize+4) -- set ptr to creatures
|
|
||||||
engine.poked(modpos+0x94,count) -- set count of creatures
|
|
||||||
engine.poked(modpos+0xb9,modpos+modsize) -- set safe location
|
|
||||||
engine.poked(modpos+0xc3,modpos+modsize) -- set safe location
|
|
||||||
SetExecute(modpos)
|
|
||||||
end
|
|
||||||
function pokeCall(off)
|
|
||||||
engine.pokeb(off,0xe8)
|
|
||||||
b=engine.peekb(off+1)
|
|
||||||
engine.poked(off+1,modpos-off-5)
|
|
||||||
engine.pokeb(off+5,b)
|
|
||||||
end
|
|
@ -1,57 +0,0 @@
|
|||||||
function friendship_in.patch()
|
|
||||||
UpdateRanges()
|
|
||||||
pos=GetTextRegion().start
|
|
||||||
local _,crace=df.sizeof(df.global.ui:_field("race_id"))
|
|
||||||
hits={}
|
|
||||||
i=1
|
|
||||||
repeat
|
|
||||||
--todo make something better/smarter...
|
|
||||||
pos1=offsets.find(pos+7,0x0f,0xBF,ANYBYTE,DWORD_,crace) -- movsx
|
|
||||||
pos2=offsets.find(pos+7,0x66,0xa1,DWORD_,crace) -- mov ax,[ptr]
|
|
||||||
pos3=offsets.find(pos+7,0xa1,DWORD_,crace) -- mov eax,[ptr]
|
|
||||||
pos4=offsets.find(pos+7,0x66,0x8b,ANYBYTE,DWORD_,crace) -- mov ANYREG,[ptr]
|
|
||||||
--pos5=offsets.find(pos+7,0x66,0x8b,0x15,DWORD_,crace) -- mov dx,[ptr]
|
|
||||||
pos=minEx{pos1,pos2,pos3,pos4}
|
|
||||||
if pos ~=0 then
|
|
||||||
hits[i]=pos
|
|
||||||
i=i+1
|
|
||||||
print(string.format("Found at %x",pos))
|
|
||||||
end
|
|
||||||
until pos==0
|
|
||||||
print("=======================================")
|
|
||||||
for _,p in pairs(hits) do
|
|
||||||
myp=p
|
|
||||||
repeat
|
|
||||||
|
|
||||||
--print(string.format("Analyzing %x...",p))
|
|
||||||
--TODO read offset from memory.xml
|
|
||||||
pos1=offsets.find(myp,0x39,ANYBYTE,0x8c,00,00,00) -- compare [reg+08c] (creature race) with any reg
|
|
||||||
pos2=offsets.find(myp,0x3b,ANYBYTE,0x8c,00,00,00) -- compare any reg with [reg+08c] (creature race)
|
|
||||||
pos=minEx{pos1,pos2}
|
|
||||||
if pos ~=0 then
|
|
||||||
|
|
||||||
if(pos-p>250) then
|
|
||||||
--this here does not work yet...
|
|
||||||
--[[pos =offsets.find(p,CALL)
|
|
||||||
print(string.format("Distance to call:%x",pos-p))
|
|
||||||
print(string.format("Call: %x",signDword(engine.peekd(pos+1)+pos)))
|
|
||||||
pos=analyzeF(signDword(signDword(engine.peekd(pos+1)+pos)))
|
|
||||||
|
|
||||||
print(string.format("Cmp @:%x",pos))]]--
|
|
||||||
print(string.format("skipping %x... Cmp too far away (dist=%i)",p,pos-p))
|
|
||||||
else
|
|
||||||
--print(string.format("Found at %x, simple compare",pos))
|
|
||||||
--print(string.format("Distance =%x",pos-p))
|
|
||||||
--patch compares
|
|
||||||
|
|
||||||
pokeCall(pos)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
break
|
|
||||||
end
|
|
||||||
myp=myp+pos+6
|
|
||||||
if myp-p >250 then break end
|
|
||||||
until false
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,18 +0,0 @@
|
|||||||
if not(FILE) then
|
|
||||||
--sanity test
|
|
||||||
--print("race num:"..engine.peekw(offsets.getEx("CurrentRace")))
|
|
||||||
--print(string.format("%x vs %x",offsets.getEx("CurrentRace"),VersionInfo.getGroup("Creatures"):getAddress("current_race")))
|
|
||||||
print("Race num:"..df.global.ui.race_id)
|
|
||||||
print("Your current race is:"..GetRaceToken(df.global.ui.race_id))
|
|
||||||
print("If this is wrong please type 'q'")
|
|
||||||
if(getline()=='q') then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
if not(FILE) then
|
|
||||||
names=ParseNames("dfusion/friendship/races.txt")--io.open("plugins/friendship/races.txt"):lines()
|
|
||||||
friendship_in.install(names)
|
|
||||||
friendship_in.patch()
|
|
||||||
end
|
|
@ -1,8 +0,0 @@
|
|||||||
DWARF
|
|
||||||
GOBLIN
|
|
||||||
ELF
|
|
||||||
HUMAN
|
|
||||||
KOBOLD
|
|
||||||
GREMLIN
|
|
||||||
TIGERMAN
|
|
||||||
ANT_MAN
|
|
@ -1 +0,0 @@
|
|||||||
as -anl --32 -o friendship_c.o friendship_c.asm
|
|
@ -1,41 +0,0 @@
|
|||||||
.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
|
|
Binary file not shown.
@ -1,89 +0,0 @@
|
|||||||
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
|
|
@ -1,57 +0,0 @@
|
|||||||
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()
|
|
@ -1,97 +0,0 @@
|
|||||||
function err(msg) --make local maybe...
|
|
||||||
print(msg)
|
|
||||||
print(debug.traceback())
|
|
||||||
end
|
|
||||||
function dofile(filename) --safer dofile, with traceback (very usefull)
|
|
||||||
f,perr=loadfile(filename)
|
|
||||||
if f~=nil then
|
|
||||||
return xpcall(f,err)
|
|
||||||
else
|
|
||||||
print(perr)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function dofile_silent(filename) --safer dofile, with traceback, no file not found error
|
|
||||||
f,perr=loadfile(filename)
|
|
||||||
if f~=nil then
|
|
||||||
return xpcall(f,err)
|
|
||||||
else
|
|
||||||
if(string.sub(perr,1,11)~="cannot open") then --ugly hack
|
|
||||||
print(perr)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function loadall(t1) --loads all non interactive plugin parts, so that later they could be used
|
|
||||||
for k,v in pairs(t1) do
|
|
||||||
dofile_silent("dfusion/"..v[1].."/init.lua")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function mainmenu(t1)
|
|
||||||
|
|
||||||
while true do
|
|
||||||
print("No. Name Desc")
|
|
||||||
for k,v in pairs(t1) do
|
|
||||||
print(string.format("%3d %15s %s",k,v[1],v[2]))
|
|
||||||
end
|
|
||||||
local q=dfhack.lineedit("Select plugin to run (q to quit):")
|
|
||||||
if q=='q' then return end
|
|
||||||
q=tonumber(q)
|
|
||||||
if q~=nil then
|
|
||||||
if q>=1 and q<=#t1 then
|
|
||||||
if t1[q][3]==nil then
|
|
||||||
dofile("dfusion/"..t1[q][1].."/plugin.lua")
|
|
||||||
else
|
|
||||||
t1[q][3]()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function RunSaved()
|
|
||||||
print("Locating saves...")
|
|
||||||
local str=df.global.world.cur_savegame.save_dir
|
|
||||||
print("Current region:"..str)
|
|
||||||
str="data/save/"..str.."/dfusion/init.lua"
|
|
||||||
print("Trying to run:"..str)
|
|
||||||
dofile_silent(str)
|
|
||||||
end
|
|
||||||
dofile("dfusion/common.lua")
|
|
||||||
dofile("dfusion/utils.lua")
|
|
||||||
dofile("dfusion/offsets_misc.lua")
|
|
||||||
dofile("dfusion/editor.lua")
|
|
||||||
--dofile("dfusion/xml_struct.lua")
|
|
||||||
unlockDF()
|
|
||||||
plugins={}
|
|
||||||
table.insert(plugins,{"simple_embark","A simple embark dwarf count editor"})
|
|
||||||
table.insert(plugins,{"tools","some misc tools"})
|
|
||||||
table.insert(plugins,{"embark","Multi race embark"})
|
|
||||||
table.insert(plugins,{"friendship","Multi race fort enabler"})
|
|
||||||
--[=[table.insert(plugins,{"items","A collection of item hacking tools"})
|
|
||||||
table.insert(plugins,{"offsets","Find all offsets"})
|
|
||||||
|
|
||||||
table.insert(plugins,{"friendship_civ","Multi civ fort enabler"})
|
|
||||||
|
|
||||||
|
|
||||||
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"})
|
|
||||||
--table.insert(plugins,{"editor","edit internals of df",EditDF})
|
|
||||||
table.insert(plugins,{"saves","run current worlds's init.lua",RunSaved})
|
|
||||||
table.insert(plugins,{"adv_tools","some tools for (mainly) adventurer hacking"})
|
|
||||||
loadall(plugins)
|
|
||||||
dofile_silent("dfusion/initcustom.lua")
|
|
||||||
|
|
||||||
local args={...}
|
|
||||||
|
|
||||||
|
|
||||||
local f,err=load(table.concat(args,' '))
|
|
||||||
if f then
|
|
||||||
f()
|
|
||||||
else
|
|
||||||
dfhack.printerr(err)
|
|
||||||
end
|
|
||||||
|
|
||||||
if not INIT then
|
|
||||||
mainmenu(plugins)
|
|
||||||
end
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
|||||||
--dofile("patterns2.lua") moved to common.lua
|
|
||||||
ptr_item={}
|
|
||||||
ptr_item.RTI={off=0,rtype=DWORD}
|
|
||||||
ptr_item.x={off=4,rtype=WORD}
|
|
||||||
ptr_item.y={off=6,rtype=WORD}
|
|
||||||
ptr_item.z={off=8,rtype=WORD}
|
|
||||||
ptr_item.ref={off=0x28,rtype=ptr_vector}
|
|
||||||
|
|
||||||
ptr_item.mat={off=0x78,rtype=WORD}
|
|
||||||
ptr_item.submat={off=0x7A,rtype=WORD}
|
|
||||||
ptr_item.submat2={off=0x7C,rtype=DWORD}
|
|
||||||
ptr_item.legendid={off=0x80,rtype=DWORD} -- i don't remember writing this...
|
|
||||||
ptr_item.decorations={off=0x90,rtype=ptr_vector}
|
|
||||||
ptr_item.flags={off=0xC,rtype=ptt_dfflag.new(8)}
|
|
||||||
ptr_item.ptr_covering={off=0x64,rtype=DWORD}
|
|
||||||
ptr_item.stack={off=0x58,rtype=WORD}
|
|
||||||
function ptr_item.getname(self,RTI)
|
|
||||||
if RTI == nil then
|
|
||||||
return string.sub(RTTI_GetName(self.RTI),5,-3)
|
|
||||||
else
|
|
||||||
return string.sub(RTTI_GetName(RTI),5,-3)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
ptr_subitems={}
|
|
||||||
ptr_subitems["item_slabst"]={}
|
|
||||||
ptr_subitems["item_slabst"].msgptr={off=0xA0,rtype=ptt_dfstring}
|
|
||||||
ptr_subitems["item_slabst"].signtype={off=0xC0,rtype=DWORD}
|
|
||||||
|
|
||||||
ptr_subitems["item_fisthst"]={}
|
|
||||||
ptr_subitems["item_fisthst"].fisthtype={off=0x78,rtype=WORD}
|
|
||||||
|
|
||||||
ptr_subitems["item_eggst"]={}
|
|
||||||
ptr_subitems["item_eggst"].race={off=0x78,rtype=DWORD}
|
|
||||||
ptr_subitems["item_eggst"].isfertile={off=0xa0,rtype=DWORD} --0 or 1
|
|
||||||
ptr_subitems["item_eggst"].hatchtime={off=0xa4,rtype=DWORD}
|
|
||||||
|
|
||||||
ptr_decoration_gen={}
|
|
||||||
ptr_decoration_gen.RTI={off=0,rtype=DWORD}
|
|
||||||
ptr_decoration_gen.material={off=0x04,rtype=WORD} -- same for all?
|
|
||||||
ptr_decoration_gen.submat={off=0x08,rtype=DWORD}
|
|
||||||
function ptr_decoration_gen.getname(self,RTI)
|
|
||||||
if RTI == nil then
|
|
||||||
return string.sub(RTTI_GetName(self.RTI),21,-5)
|
|
||||||
else
|
|
||||||
return string.sub(RTTI_GetName(RTI),21,-5)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
ptr_decoration={}
|
|
||||||
ptr_decoration["covered"]={}
|
|
||||||
ptr_decoration["covered"].material={off=0x04,rtype=WORD}
|
|
||||||
ptr_decoration["covered"].submat={off=0x08,rtype=DWORD}
|
|
||||||
ptr_decoration["art_image"]={}
|
|
||||||
ptr_decoration["art_image"].material={off=0x04,rtype=WORD}
|
|
||||||
ptr_decoration["art_image"].submat={off=0x08,rtype=DWORD}
|
|
||||||
ptr_decoration["art_image"].image={off=0x24,rtype=DWORD}
|
|
||||||
ptr_decoration["bands"]={}
|
|
||||||
ptr_decoration["bands"].material={off=0x04,rtype=WORD}
|
|
||||||
ptr_decoration["bands"].submat={off=0x08,rtype=DWORD}
|
|
||||||
ptr_cover={} --covering of various types (blood, water, etc)
|
|
||||||
ptr_cover.mat={off=0,rtype=WORD}
|
|
||||||
ptr_cover.submat={off=4,rtype=DWORD}
|
|
||||||
ptr_cover.state={off=8,rtype=WORD}
|
|
@ -1,212 +0,0 @@
|
|||||||
items={} --> first lets make a menu table
|
|
||||||
items.menu=MakeMenu()
|
|
||||||
|
|
||||||
|
|
||||||
function items.dest()
|
|
||||||
myoff=offsets.getEx("Items") -- first find out where "item vector" is
|
|
||||||
vector=engine.peek(myoff,ptr_vector) -- get list of items
|
|
||||||
for i=0,vector:size()-1 do --look at each item
|
|
||||||
flg=engine.peek(vector:getval(i),ptr_item.flags)
|
|
||||||
flg:set(17,1)
|
|
||||||
engine.poke(vector:getval(i),ptr_item.flags,flg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function items.eggs()
|
|
||||||
myoff=offsets.getEx("Items") -- first find out where "item vector" is
|
|
||||||
vector=engine.peek(myoff,ptr_vector) -- get list of items
|
|
||||||
for i=0,vector:size()-1 do --look at each item
|
|
||||||
rti=engine.peek(vector:getval(i),ptr_item.RTI)
|
|
||||||
if ptr_item.getname(nil,rti)=="item_eggst" then
|
|
||||||
egg=engine.peek(vector:getval(i),ptr_subitems["item_eggst"])
|
|
||||||
egg.isfertile=1
|
|
||||||
egg.hatchtime=0xffffff
|
|
||||||
--egg.race=123 -- change race for fun times
|
|
||||||
engine.poke(vector:getval(i),ptr_subitems["item_eggst"],egg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function editFlags(offset)
|
|
||||||
while true do
|
|
||||||
flags=engine.peek(offset,ptr_item.flags)
|
|
||||||
for i=0,8*8-1 do
|
|
||||||
if flags:get(i) then
|
|
||||||
print(i.." is true")
|
|
||||||
else
|
|
||||||
print(i.." is false")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
print(" enter number to switch flag or not a number to quit:")
|
|
||||||
q=tonumber(io.stdin:read())
|
|
||||||
if q==nil then return end
|
|
||||||
flags:flip(q)
|
|
||||||
engine.poke(offset,ptr_item.flags,flags)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function editCovering(offset)
|
|
||||||
off=engine.peek(offset,ptr_item.ptr_covering)
|
|
||||||
if off == 0 then
|
|
||||||
print("No coverings found.")
|
|
||||||
end
|
|
||||||
vec=engine.peek(off,ptr_vector)
|
|
||||||
print("Covering list:")
|
|
||||||
for i=0,vec:size()-1 do
|
|
||||||
cov=engine.peek(vec:getval(i),ptr_cover)
|
|
||||||
print(string.format("%d. mat=%d submat=%d state=%d",i,cov.mat,cov.submat,cov.state))
|
|
||||||
end
|
|
||||||
print("To edit type number:")
|
|
||||||
q=tonumber(io.stdin:read())
|
|
||||||
if q==nil then return end
|
|
||||||
if q>=vec:size() or q<0 then return end
|
|
||||||
off=vec:getval(q)
|
|
||||||
cov=engine.peek(off,ptr_cover)
|
|
||||||
print("Enter mat:")
|
|
||||||
q=tonumber(io.stdin:read())
|
|
||||||
if q==nil then q=0xffff end
|
|
||||||
print("Enter submat:")
|
|
||||||
v=tonumber(io.stdin:read())
|
|
||||||
if v==nil then v=0xffff end
|
|
||||||
print("Enter state:")
|
|
||||||
y=tonumber(io.stdin:read())
|
|
||||||
if y==nil then y=0 end
|
|
||||||
cov.mat=q
|
|
||||||
cov.submat=v
|
|
||||||
cov.state=y
|
|
||||||
engine.poke(off,ptr_cover,cov)
|
|
||||||
end
|
|
||||||
function editMaterial(offset)
|
|
||||||
print("Mat id 0 to 18 is in normal materials (inorganic, amber etc...) after that creature mat (with submat2 being race)")
|
|
||||||
print("from 219 with submat2=0xffffffff (type not a number) it reads legends id, from 419 submat2 means plant id")
|
|
||||||
print("Probably submat is not used :? ")
|
|
||||||
mat=engine.peek(offset,ptr_item.mat)
|
|
||||||
submat=engine.peek(offset,ptr_item.submat)
|
|
||||||
submat2=engine.peek(offset,ptr_item.submat2)
|
|
||||||
lid=engine.peek(offset,ptr_item.legendid)
|
|
||||||
print(string.format("Now is mat=%d, submat=%d submat2=%d legend id=%d",mat,submat,submat2,lid))
|
|
||||||
print("Enter mat:")
|
|
||||||
q=tonumber(io.stdin:read())
|
|
||||||
if q==nil then return end
|
|
||||||
print("Enter submat:")
|
|
||||||
v=tonumber(io.stdin:read())
|
|
||||||
if v==nil then v=0xffff end
|
|
||||||
print("Enter submat2:")
|
|
||||||
z=tonumber(io.stdin:read())
|
|
||||||
if z==nil then z=0xffffffff end
|
|
||||||
print("Enter legendid:")
|
|
||||||
y=tonumber(io.stdin:read())
|
|
||||||
if y==nil then y=0xffffffff end
|
|
||||||
engine.poke(offset,ptr_item.mat,q)
|
|
||||||
engine.poke(offset,ptr_item.submat,v)
|
|
||||||
engine.poke(offset,ptr_item.legendid,y)
|
|
||||||
engine.poke(offset,ptr_item.submat2,z)
|
|
||||||
print("Done")
|
|
||||||
end
|
|
||||||
function items.select()
|
|
||||||
myoff=offsets.getEx("Items")
|
|
||||||
vector=engine.peek(myoff,ptr_vector)
|
|
||||||
tx,ty,tz=getxyz()
|
|
||||||
T={}
|
|
||||||
for i=0,vector:size()-1 do --this finds all item offsets that are on pointer
|
|
||||||
itoff=vector:getval(i)
|
|
||||||
x=engine.peek(itoff,ptr_item.x)
|
|
||||||
y=engine.peek(itoff,ptr_item.y)
|
|
||||||
z=engine.peek(itoff,ptr_item.z)
|
|
||||||
if x==tx and y==ty and z==tz then
|
|
||||||
table.insert(T,itoff)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
print("Items under cursor:")
|
|
||||||
i=1
|
|
||||||
for _,v in pairs(T) do
|
|
||||||
RTI=engine.peek(v,ptr_item.RTI)
|
|
||||||
print(i..". "..ptr_item.getname(nil,RTI))
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
print("Type number to edit or 'q' to exit")
|
|
||||||
while true do
|
|
||||||
q=io.stdin:read()
|
|
||||||
if q=='q' then return end
|
|
||||||
if tonumber(q) ~=nil and tonumber(q)<i then break end
|
|
||||||
end
|
|
||||||
return T[tonumber(q)]
|
|
||||||
end
|
|
||||||
function items.select_creature(croff)
|
|
||||||
vector=engine.peek(croff,ptr_Creature.itemlist2)
|
|
||||||
print("Vector size:"..vector:size())
|
|
||||||
T={}
|
|
||||||
for i=0,vector:size()-1 do
|
|
||||||
table.insert(T,vector:getval(i)) -- item list is itemptr+location?
|
|
||||||
end
|
|
||||||
print("Items in inventory:")
|
|
||||||
i=1
|
|
||||||
for _,v in pairs(T) do
|
|
||||||
RTI=engine.peek(engine.peekd(v),ptr_item.RTI)
|
|
||||||
print(i..". "..ptr_item.getname(nil,RTI).." locations:"..engine.peekw(v+4).." "..engine.peekw(v+6))
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
print("Type number to edit or 'q' to exit")
|
|
||||||
while true do
|
|
||||||
q=io.stdin:read()
|
|
||||||
if q=='q' then return end
|
|
||||||
if tonumber(q) ~=nil and tonumber(q)<i then break end
|
|
||||||
end
|
|
||||||
return engine.peekd(T[tonumber(q)])
|
|
||||||
end
|
|
||||||
function items.edit(itoff)
|
|
||||||
if itoff==nil then
|
|
||||||
itoff=items.select()
|
|
||||||
end
|
|
||||||
print(string.format("Item offset:%x",itoff))
|
|
||||||
print("Type what to edit:")
|
|
||||||
print("1. material")
|
|
||||||
print("2. flags")
|
|
||||||
print("3. covering")
|
|
||||||
Z={}
|
|
||||||
Z[1]=editMaterial
|
|
||||||
Z[2]=editFlags
|
|
||||||
Z[3]=editCovering
|
|
||||||
name=ptr_item.getname(nil,engine.peek(itoff,ptr_item.RTI))
|
|
||||||
if name~=nil and ptr_subitems[name]~=nil then
|
|
||||||
print("4. Item specific edit")
|
|
||||||
--Z[4]=items.fedit[name]
|
|
||||||
Z[4]="dummy"
|
|
||||||
end
|
|
||||||
while true do
|
|
||||||
q=io.stdin:read()
|
|
||||||
if q=='q' then return end
|
|
||||||
if tonumber(q) ~=nil and tonumber(q)<#Z+1 then break end
|
|
||||||
end
|
|
||||||
|
|
||||||
if Z[tonumber(q)]=="dummy" then
|
|
||||||
ModPattern(itoff,ptr_subitems[name])
|
|
||||||
else
|
|
||||||
Z[tonumber(q)](itoff)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function items.printref()
|
|
||||||
itoff=items.select()
|
|
||||||
vec=engine.peek(itoff,ptr_item.ref)
|
|
||||||
for i=0, vec:size()-1 do
|
|
||||||
toff=vec:getval(i)
|
|
||||||
print(RTTI_GetName(engine.peekd(toff)))
|
|
||||||
end
|
|
||||||
print("Decorations:")
|
|
||||||
vec=engine.peek(itoff,ptr_item.decorations)
|
|
||||||
for i=0, vec:size()-1 do
|
|
||||||
toff=vec:getval(i)
|
|
||||||
print(ptr_decoration_gen.getname(nil,engine.peek(toff,ptr_decoration_gen.RTI)))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function items.edit_adv()
|
|
||||||
vec=engine.peek(offsets.getEx("CreatureVec"),ptr_vector)
|
|
||||||
items.edit(items.select_creature(vec:getval(0)))
|
|
||||||
end
|
|
||||||
if not(FILE) then -- if not in script mode
|
|
||||||
|
|
||||||
items.menu:add("Destroy all",items.dest)
|
|
||||||
items.menu:add("Hatch eggs",items.eggs)
|
|
||||||
items.menu:add("Edit item",items.edit)
|
|
||||||
items.menu:add("Print ref",items.printref)
|
|
||||||
items.menu:add("Edit adventurer's items",items.edit_adv)
|
|
||||||
items.menu:display()
|
|
||||||
|
|
||||||
end
|
|
@ -1 +0,0 @@
|
|||||||
as -anl --32 -o migrants.o migrants.asm
|
|
@ -1,62 +0,0 @@
|
|||||||
--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",400)
|
|
||||||
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
|
|
||||||
_,raceoff=df.sizeof(df.global.ui:_field('race_id'))
|
|
||||||
pos=offsets.find(offsets.base(),0xa1,DWORD_,raceoff,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,20 +0,0 @@
|
|||||||
.intel_syntax
|
|
||||||
pushfd
|
|
||||||
push ebx
|
|
||||||
push edx
|
|
||||||
mov eax,[0xdeadbeef] # get old seed
|
|
||||||
mov ebx,1103515245
|
|
||||||
#mul 1103515245
|
|
||||||
mul ebx
|
|
||||||
add eax,12345
|
|
||||||
mov [0xdeadbeef],eax #put seed back...thus generation rnd is complete
|
|
||||||
|
|
||||||
xor edx,edx
|
|
||||||
mov ebx,2000 #put size of array here
|
|
||||||
div ebx #why oh why there is no div const? compiler prob makes some xor/add magic
|
|
||||||
movzx eax,word ptr[0xdeadbeef+edx*2]
|
|
||||||
pop edx
|
|
||||||
pop ebx
|
|
||||||
|
|
||||||
popfd
|
|
||||||
ret
|
|
Binary file not shown.
@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
if not(FILE) then
|
|
||||||
names=ParseNames("dfusion/migrants/races.txt")--io.open("plugins/migrants/races.txt"):lines()
|
|
||||||
migrants(names)
|
|
||||||
end
|
|
@ -1,29 +0,0 @@
|
|||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
ELF
|
|
||||||
HUMAN
|
|
||||||
DWARF
|
|
||||||
GREMLIN
|
|
||||||
KOBOLD
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
DWARF
|
|
||||||
ELF
|
|
||||||
HUMAN
|
|
||||||
DWARF
|
|
||||||
GREMLIN
|
|
||||||
KOBOLD
|
|
||||||
DEMON_13
|
|
@ -1,2 +0,0 @@
|
|||||||
offsets.searchoffsets()
|
|
||||||
offsets.save()
|
|
@ -1,48 +0,0 @@
|
|||||||
offsets=offsets or {}
|
|
||||||
function offsets.find(startoffset,...)
|
|
||||||
-- [=[
|
|
||||||
if startoffset== 0 then
|
|
||||||
local text=GetTextRegion()
|
|
||||||
--print("searching in:"..text.name)
|
|
||||||
startoffset=text.start
|
|
||||||
endadr=text["end"]
|
|
||||||
else
|
|
||||||
local reg=GetRegionIn(startoffset)
|
|
||||||
--print("searching in:"..reg.name)
|
|
||||||
if reg==nil then
|
|
||||||
print(string.format("Warning: memory range for search @:%x not found!",startoffset))
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
endadr=reg["end"]
|
|
||||||
end
|
|
||||||
--]=]
|
|
||||||
--print(string.format("Searching (%x->%x)",startoffset,endadr))
|
|
||||||
local h=hexsearch(startoffset,endadr,...)
|
|
||||||
local pos=h:find()
|
|
||||||
h=nil
|
|
||||||
return pos
|
|
||||||
end
|
|
||||||
function offsets.findall(startoffset,...)
|
|
||||||
local endadr;
|
|
||||||
if startoffset== 0 then
|
|
||||||
local text=GetTextRegion()
|
|
||||||
--print("searching in:"..text.name)
|
|
||||||
startoffset=text.start
|
|
||||||
endadr=text["end"]
|
|
||||||
else
|
|
||||||
local reg=GetRegionIn(startoffset)
|
|
||||||
--print("searching in:"..reg.name)
|
|
||||||
endadr=reg["end"]
|
|
||||||
end
|
|
||||||
local h=hexsearch(startoffset,endadr,...)
|
|
||||||
local pos=h:findall()
|
|
||||||
h=nil
|
|
||||||
return pos
|
|
||||||
end
|
|
||||||
function offsets.base()
|
|
||||||
return Process.getBase()
|
|
||||||
end
|
|
||||||
function offsets.getvectors()
|
|
||||||
return findVectors()
|
|
||||||
end
|
|
||||||
ADDRESS=ANYDWORD
|
|
@ -1,248 +0,0 @@
|
|||||||
ptt_dfstring={}
|
|
||||||
if WINDOWS then
|
|
||||||
ptt_dfstring.ptr={off=0,rtype=DWORD}
|
|
||||||
ptt_dfstring.size={off=16,rtype=DWORD}
|
|
||||||
ptt_dfstring.alloc={off=20,rtype=DWORD}
|
|
||||||
|
|
||||||
function ptt_dfstring:getval()
|
|
||||||
--print(string.format("GETTING FROM:%x",self.__offset))
|
|
||||||
if self.size<16 then
|
|
||||||
--print(string.format("GETTING FROM:%x",self.__offset))
|
|
||||||
return string.sub(engine.peekstr(self.__offset),1,self.size)
|
|
||||||
else
|
|
||||||
--print(string.format("GETTING FROM:%x",self.ptr))
|
|
||||||
return string.sub(engine.peekstr(self.ptr),1,self.size)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function ptt_dfstring:setval(newstring)
|
|
||||||
local offset=self.__offset
|
|
||||||
local strl=string.len(newstring)
|
|
||||||
if strl<16 then
|
|
||||||
--print(string.format("GETTING FROM:%x",self.__offset))
|
|
||||||
|
|
||||||
engine.poked(offset+ptt_dfstring.size.off,strl)
|
|
||||||
engine.poked(offset+ptt_dfstring.alloc.off,15)
|
|
||||||
engine.pokestr(offset,newstring)
|
|
||||||
|
|
||||||
else
|
|
||||||
local loc
|
|
||||||
if engine.peekd(offset+ptt_dfstring.alloc.off) > strl then
|
|
||||||
loc=engine.peekd(offset)
|
|
||||||
print("Will fit:"..loc.." len:"..strl)
|
|
||||||
else
|
|
||||||
loc=Allocate(strl+1)
|
|
||||||
engine.poked(offset+ptt_dfstring.alloc.off,strl)
|
|
||||||
print("Will not fit:"..loc.." len:"..strl)
|
|
||||||
end
|
|
||||||
--print(string.format("GETTING FROM:%x",self.ptr))
|
|
||||||
engine.poked(self.__offset+ptt_dfstring.size.off,strl)
|
|
||||||
engine.pokestr(loc,newstring)
|
|
||||||
engine.poked(self.__offset,loc)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
--ptt_dfstring.ptr={off=0,rtype=DWORD}
|
|
||||||
function ptt_dfstring:getval()
|
|
||||||
return engine.peekstr_stl(self.__offset)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--if(COMPATMODE) then
|
|
||||||
--ptr_vector={}
|
|
||||||
--ptr_vector.st={off=4,rtype=DWORD}
|
|
||||||
--ptr_vector.en={off=8,rtype=DWORD}
|
|
||||||
--else
|
|
||||||
ptr_vector={}
|
|
||||||
ptr_vector.st={off=0,rtype=DWORD}
|
|
||||||
ptr_vector.en={off=4,rtype=DWORD}
|
|
||||||
ptr_vector.alloc={off=8,rtype=DWORD}
|
|
||||||
--end
|
|
||||||
function ptr_vector:clone(settype)
|
|
||||||
local ret={}
|
|
||||||
for k,v in pairs(self) do
|
|
||||||
ret[k]=v
|
|
||||||
end
|
|
||||||
ret.type=settype
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
function ptr_vector:size()
|
|
||||||
return (self.en-self.st)/engine.sizeof(self.type)
|
|
||||||
end
|
|
||||||
ptr_vector.type=DWORD
|
|
||||||
function ptr_vector:getval(num)
|
|
||||||
if self.st==0 then return error("Vector empty.") end
|
|
||||||
--print("Wants:"..num.." size:"..self:size())
|
|
||||||
if num>=self:size() then error("Index out of bounds in vector.") end
|
|
||||||
return engine.peek(self.st+engine.sizeof(self.type)*num,self.type)
|
|
||||||
end
|
|
||||||
function ptr_vector:setval(num,val)
|
|
||||||
return engine.poke(self.st+engine.sizeof(self.type)*num,self.type,val)
|
|
||||||
end
|
|
||||||
function ptr_vector:append(val)
|
|
||||||
if self.alloc - self.en > 0 then
|
|
||||||
local num=self:size()
|
|
||||||
self.en=self.en+engine.sizeof(self.type)
|
|
||||||
self:setval(val,num)
|
|
||||||
else
|
|
||||||
error("larger than allocated arrays not implemented yet")
|
|
||||||
local num=self:size()
|
|
||||||
local ptr=Allocate(num*2)
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
ptt_dfflag={}
|
|
||||||
function ptt_dfflag.flip(self,num) --flip one bit in flags
|
|
||||||
local of=math.floor (num/8);
|
|
||||||
|
|
||||||
self[of]=bit.bxor(self[of],bit.lshift(1,num%8))
|
|
||||||
end
|
|
||||||
|
|
||||||
function ptt_dfflag.get(self,num) -- get one bit in flags
|
|
||||||
local of=math.floor (num/8);
|
|
||||||
|
|
||||||
if bit.band(self[of],bit.lshift(1,num%8))~=0 then
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function ptt_dfflag.set(self,num,val) --set to on or off one bit in flags
|
|
||||||
if (self:get(num)~=val) then
|
|
||||||
self:flip(num)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function ptt_dfflag.new(size) -- create new flag pattern of size(in bytes)
|
|
||||||
local ret={}
|
|
||||||
for i=0,size-1 do
|
|
||||||
ret[i]={off=i,rtype=BYTE};
|
|
||||||
end
|
|
||||||
ret.flip=ptt_dfflag.flip --change to metatable stuff...
|
|
||||||
ret.get=ptt_dfflag.get
|
|
||||||
ret.set=ptt_dfflag.set
|
|
||||||
return ret;
|
|
||||||
end
|
|
||||||
--[[
|
|
||||||
Creature:
|
|
||||||
0 name (df_string) 28
|
|
||||||
28 nick (df_string) 56
|
|
||||||
56 surname- namearray(7*dword(4)) 84 ...
|
|
||||||
140 race (dword) 144
|
|
||||||
224 flags
|
|
||||||
264 civ (dword)
|
|
||||||
252 ID
|
|
||||||
592 following ID
|
|
||||||
904 bleed vector? hurt vector or sth...
|
|
||||||
0x790 legends id?
|
|
||||||
2128 known names? or knowledge?
|
|
||||||
flags:
|
|
||||||
0 Can the dwarf move or are they waiting for their movement timer
|
|
||||||
1 Dead (might also be set for incoming/leaving critters that are alive)
|
|
||||||
2 Currently in mood
|
|
||||||
3 Had a mood
|
|
||||||
4 "marauder" -- wide class of invader/inside creature attackers
|
|
||||||
5 Drowning
|
|
||||||
6 Active merchant
|
|
||||||
7 "forest" (used for units no longer linked to merchant/diplomacy, they just try to leave mostly)
|
|
||||||
8 Left (left the map)
|
|
||||||
9 Rider
|
|
||||||
10 Incoming
|
|
||||||
11 Diplomat
|
|
||||||
12 Zombie
|
|
||||||
13 Skeleton
|
|
||||||
14 Can swap tiles during movement (prevents multiple swaps)
|
|
||||||
15 On the ground (can be conscious)
|
|
||||||
16 Projectile
|
|
||||||
17 Active invader (for organized ones)
|
|
||||||
18 Hidden in ambush
|
|
||||||
19 Invader origin (could be inactive and fleeing)
|
|
||||||
20 Will flee if invasion turns around
|
|
||||||
21 Active marauder/invader moving inward
|
|
||||||
22 Marauder resident/invader moving in all the way
|
|
||||||
23 Check against flows next time you get a chance
|
|
||||||
24 Ridden
|
|
||||||
25 Caged
|
|
||||||
26 Tame
|
|
||||||
27 Chained
|
|
||||||
28 Royal guard
|
|
||||||
29 Fortress guard
|
|
||||||
30 Suppress wield for beatings/etc
|
|
||||||
31 Is an important historical figure
|
|
||||||
32 swiming
|
|
||||||
|
|
||||||
]]--
|
|
||||||
ptr_Creature={}
|
|
||||||
local posoff=0 --VersionInfo.getGroup("Creatures"):getGroup("creature"):getOffset("position")
|
|
||||||
ptr_Creature.x={off=posoff,rtype=WORD} --ok
|
|
||||||
ptr_Creature.y={off=posoff+2,rtype=WORD} --ok
|
|
||||||
ptr_Creature.z={off=posoff+4,rtype=WORD} --ok
|
|
||||||
ptr_Creature.flags={off=0,rtype=ptt_dfflag.new(10)}
|
|
||||||
ptr_Creature.name={off=0,rtype=ptt_dfstring}
|
|
||||||
ptr_Creature.ID={off=252,rtype=DWORD} --ok i guess
|
|
||||||
ptr_Creature.followID={off=592,rtype=DWORD} --ok
|
|
||||||
ptr_Creature.race={off=140,rtype=DWORD} --ok
|
|
||||||
ptr_Creature.civ={off=264,rtype=DWORD}
|
|
||||||
ptr_Creature.legends={off=344,rtype=ptr_vector} --ok
|
|
||||||
ptr_Creature.hurt1={off=0x308,rtype=ptr_vector:clone(BYTE)} --byte vector...
|
|
||||||
ptr_Creature.hurt2={off=0x338,rtype=ptr_vector}
|
|
||||||
ptr_Creature.wounds={off=0x388,rtype=ptr_vector}
|
|
||||||
ptr_Creature.itemlist1={off=0x1D0,rtype=ptr_vector}
|
|
||||||
ptr_Creature.itemlist2={off=0x288,rtype=ptr_vector}
|
|
||||||
ptr_Creature.bloodlvl={off=0x490,rtype=DWORD}
|
|
||||||
ptr_Creature.bleedlvl={off=0x494,rtype=DWORD}
|
|
||||||
|
|
||||||
ptr_CrGloss={}
|
|
||||||
ptr_CrGloss.token={off=0,rtype=ptt_dfstring}
|
|
||||||
ptr_CrGloss.castes={off=296,rtype=ptr_vector}
|
|
||||||
|
|
||||||
ptr_CrCaste={}
|
|
||||||
ptr_CrCaste.name={off=0,rtype=ptt_dfstring}
|
|
||||||
ptr_CrCaste.flags_ptr={off=0x5A0,rtype=DWORD} --size 17?
|
|
||||||
--[=[
|
|
||||||
Flags:
|
|
||||||
57 - is sentient (allows setting labours)
|
|
||||||
--]=]
|
|
||||||
ptr_LEntry={} -- all size 256
|
|
||||||
ptr_LEntry.name={off=36,rtype=ptt_dfstring}
|
|
||||||
ptr_LEntry.id1={off=160,rtype=DWORD}
|
|
||||||
ptr_LEntry.id2={off=164,rtype=DWORD}
|
|
||||||
ptr_LEntry.somlist={off=220,rtype=DWORD}
|
|
||||||
|
|
||||||
ptr_dfname={}
|
|
||||||
for i=0,6 do
|
|
||||||
ptr_dfname[i]={off=i*4,rtype=DWORD}
|
|
||||||
end
|
|
||||||
--[[
|
|
||||||
Site docs:
|
|
||||||
0x38 name struct todo...
|
|
||||||
0x78 type:
|
|
||||||
0 - mountain halls (yours)
|
|
||||||
1 - dark fort
|
|
||||||
2 - cave
|
|
||||||
3 - mountain hall (other)
|
|
||||||
4 - forest
|
|
||||||
5 - hamlet
|
|
||||||
6 - imp location
|
|
||||||
7 - lair
|
|
||||||
8 - fort
|
|
||||||
9 - camp
|
|
||||||
0x7a some sort of id?
|
|
||||||
0x84 some vec (ids)
|
|
||||||
0x94 some other vec (ids)
|
|
||||||
0xa4 some vec (prts)
|
|
||||||
0x118 ptr to sth
|
|
||||||
|
|
||||||
0x14c ptr to mapdata
|
|
||||||
]]--
|
|
||||||
|
|
||||||
|
|
||||||
ptr_site={}
|
|
||||||
ptr_site.type={off=0x78,rtype=WORD}
|
|
||||||
ptr_site.id={off=0x7a,rtype=DWORD}
|
|
||||||
ptr_site.name={off=0x38,rtype=ptr_dfname}
|
|
||||||
ptr_site.flagptr={off=0x118,rtype=DWORD}
|
|
||||||
|
|
||||||
ptr_legends2={}
|
|
||||||
ptr_legends2.id={off=0,rtype=DWORD}
|
|
||||||
ptr_legends2.follow={off=0x18,rtype=DWORD}
|
|
||||||
|
|
||||||
ptr_material={}
|
|
||||||
ptr_material.token={off=0,rtype=ptt_dfstring}
|
|
@ -1,7 +0,0 @@
|
|||||||
<ld:data-definition xmlns:ld="http://github.com/peterix/dfhack/lowered-data-definition">
|
|
||||||
<ld:global-type ld:meta="struct-type" type-name="coord">
|
|
||||||
<ld:field name="x" ld:meta="number" ld:subtype="int16_t" ld:bits="16"/>
|
|
||||||
<ld:field name="y" ld:meta="number" ld:subtype="int16_t" ld:bits="16"/>
|
|
||||||
<ld:field name="z" ld:meta="number" ld:subtype="int16_t" ld:bits="16"/>
|
|
||||||
</ld:global-type>
|
|
||||||
</ld:data-definition>
|
|
@ -1,55 +0,0 @@
|
|||||||
|
|
||||||
function parseargs(s)
|
|
||||||
local arg = {}
|
|
||||||
string.gsub(s, "([%w%-]+)=([\"'])(.-)%2", function (w, _, a)
|
|
||||||
arg[w] = a
|
|
||||||
end)
|
|
||||||
return arg
|
|
||||||
end
|
|
||||||
|
|
||||||
function collect(s)
|
|
||||||
local stack = {}
|
|
||||||
local top = {}
|
|
||||||
table.insert(stack, top)
|
|
||||||
local ni,c,label,xarg, empty
|
|
||||||
local i, j = 1, 1
|
|
||||||
while true do
|
|
||||||
ni,j,c,label,xarg, empty = string.find(s, "<(%/?)([%w:%-]+)(.-)(%/?)>", i)
|
|
||||||
if not ni then break end
|
|
||||||
local text = string.sub(s, i, ni-1)
|
|
||||||
if not string.find(text, "^%s*$") then
|
|
||||||
table.insert(top, text)
|
|
||||||
end
|
|
||||||
if empty == "/" then -- empty element tag
|
|
||||||
table.insert(top, {label=label, xarg=parseargs(xarg), empty=1})
|
|
||||||
elseif c == "" then -- start tag
|
|
||||||
top = {label=label, xarg=parseargs(xarg)}
|
|
||||||
table.insert(stack, top) -- new level
|
|
||||||
else -- end tag
|
|
||||||
local toclose = table.remove(stack) -- remove top
|
|
||||||
top = stack[#stack]
|
|
||||||
if #stack < 1 then
|
|
||||||
error("nothing to close with "..label)
|
|
||||||
end
|
|
||||||
if toclose.label ~= label then
|
|
||||||
error("trying to close "..toclose.label.." with "..label)
|
|
||||||
end
|
|
||||||
table.insert(top, toclose)
|
|
||||||
end
|
|
||||||
i = j+1
|
|
||||||
end
|
|
||||||
local text = string.sub(s, i)
|
|
||||||
if not string.find(text, "^%s*$") then
|
|
||||||
table.insert(stack[#stack], text)
|
|
||||||
end
|
|
||||||
if #stack > 1 then
|
|
||||||
error("unclosed "..stack[#stack].label)
|
|
||||||
end
|
|
||||||
return stack[1]
|
|
||||||
end
|
|
||||||
|
|
||||||
function parseXmlFile(path)
|
|
||||||
local f, e = io.open(path, "r")
|
|
||||||
local xml = f:read("*a")
|
|
||||||
return collect(xml)
|
|
||||||
end
|
|
@ -1,29 +0,0 @@
|
|||||||
ptr_COL={} -- complete object locator...
|
|
||||||
ptr_COL.sig={off=0,rtype=DWORD}
|
|
||||||
ptr_COL.offset={off=4,rtype=DWORD} --offset of this vtable in the complete class
|
|
||||||
ptr_COL.cdoffset={off=8,rtype=DWORD} -- constructor displacement
|
|
||||||
ptr_COL.typePointer={off=12,rtype=DWORD}
|
|
||||||
ptr_COL.hierarchyPointer={off=16,rtype=DWORD}
|
|
||||||
|
|
||||||
ptr_RTTI_Type={}
|
|
||||||
ptr_RTTI_Type.vftPointer={off=0,rtype=DWORD}
|
|
||||||
ptr_RTTI_Type.name={off=8,rtype=STD_STRING}
|
|
||||||
|
|
||||||
function RTTI_GetName(vtable)
|
|
||||||
local COLoff=engine.peek(vtable-4,DWORD)
|
|
||||||
--print(string.format("Look:%x vtable:%x",vtable,engine.peek(vtable-4,DWORD)))
|
|
||||||
COL=engine.peek(COLoff,ptr_COL)
|
|
||||||
--print(string.format("COL:%x Typeptr:%x Type:%s",COLoff,COL.typePointer,engine.peek(COL.typePointer,ptr_RTTI_Type.name)))
|
|
||||||
return engine.peek(COL.typePointer,ptr_RTTI_Type.name)
|
|
||||||
end
|
|
||||||
ptr_RTTI_Hierarchy={}
|
|
||||||
ptr_RTTI_Hierarchy.sig={off=0,rtype=DWORD}
|
|
||||||
ptr_RTTI_Hierarchy.attributes={off=4,rtype=DWORD}
|
|
||||||
ptr_RTTI_Hierarchy.numBaseClasses={off=8,rtype=DWORD}
|
|
||||||
ptr_RTTI_Hierarchy.ptrBases={off=12,rtype=DWORD}
|
|
||||||
|
|
||||||
ptr_RTTI_BaseClass={}
|
|
||||||
ptr_RTTI_BaseClass.typePointer={off=0,rtype=DWORD}
|
|
||||||
ptr_RTTI_BaseClass.numContained={off=4,rtype=DWORD}
|
|
||||||
--todo PMD
|
|
||||||
--todo flags
|
|
@ -1,15 +0,0 @@
|
|||||||
function simple_embark(num)
|
|
||||||
stoff=VersionInfo.getAddress('start_dwarf_count')
|
|
||||||
print("Starting dwarves found:"..engine.peekd(stoff))
|
|
||||||
engine.poked(stoff,num)
|
|
||||||
end
|
|
||||||
if not(FILE) then
|
|
||||||
print("Type in new ammount:")
|
|
||||||
repeat
|
|
||||||
ans=tonumber(io.read())
|
|
||||||
if ans==nil or not(ans<=15000 and ans>0) then
|
|
||||||
print("incorrect choice")
|
|
||||||
end
|
|
||||||
until ans~=nil and (ans<=15000 and ans>0)
|
|
||||||
simple_embark(ans)
|
|
||||||
end
|
|
@ -1,497 +0,0 @@
|
|||||||
tools={}
|
|
||||||
tools.menu=MakeMenu()
|
|
||||||
function tools.setrace(name)
|
|
||||||
RaceTable=BuildNameTable()
|
|
||||||
print("Your current race is:"..GetRaceToken(df.global.ui.race_id))
|
|
||||||
local id
|
|
||||||
if name == nil then
|
|
||||||
print("Type new race's token name in full caps (q to quit):")
|
|
||||||
repeat
|
|
||||||
entry=getline()
|
|
||||||
if entry=="q" then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
id=RaceTable[entry]
|
|
||||||
until id~=nil
|
|
||||||
else
|
|
||||||
id=RaceTable[name]
|
|
||||||
if id==nil then
|
|
||||||
error("Name not found!")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
df.global.ui.race_id=id
|
|
||||||
end
|
|
||||||
tools.menu:add("Set current race",tools.setrace)
|
|
||||||
function tools.GiveSentience(names)
|
|
||||||
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=getline()
|
|
||||||
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 races=df.global.world.raws.creatures.all
|
|
||||||
|
|
||||||
local castes=races[id].caste
|
|
||||||
print(string.format("Caste count:%i",castes.size))
|
|
||||||
for i =0,#castes-1 do
|
|
||||||
|
|
||||||
print("Caste name:"..castes[i].caste_id.."...")
|
|
||||||
|
|
||||||
local flags=castes[i].flags
|
|
||||||
--print(string.format("%x",flagoffset))
|
|
||||||
if flags.CAN_SPEAK then
|
|
||||||
print("\tis sentient.")
|
|
||||||
else
|
|
||||||
print("\tnon sentient. Allocating IQ...")
|
|
||||||
flags.CAN_SPEAK=true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
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.getCreatureId(vector) --redo it to getcreature by name/id or something
|
|
||||||
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=getline()
|
|
||||||
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(unit,nemesis)
|
|
||||||
if nemesis==nil then
|
|
||||||
nemesis=true --default value is nemesis switch too.
|
|
||||||
end
|
|
||||||
if unit==nil then
|
|
||||||
unit=getCreatureAtPointer()
|
|
||||||
end
|
|
||||||
if unit==nil then
|
|
||||||
error("Invalid unit!")
|
|
||||||
end
|
|
||||||
local other=df.global.world.units.active
|
|
||||||
local unit_indx
|
|
||||||
for k,v in pairs(other) do
|
|
||||||
if v==unit then
|
|
||||||
unit_indx=k
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if unit_indx==nil then
|
|
||||||
error("Unit not found in array?!") --should not happen
|
|
||||||
end
|
|
||||||
other[unit_indx]=other[0]
|
|
||||||
other[0]=unit
|
|
||||||
if nemesis then --basicly copied from advtools plugin...
|
|
||||||
local nem=getNemesis(unit)
|
|
||||||
local other_nem=getNemesis(other[unit_indx])
|
|
||||||
if other_nem then
|
|
||||||
other_nem.flags[0]=false
|
|
||||||
other_nem.flags[1]=true
|
|
||||||
end
|
|
||||||
if nem then
|
|
||||||
nem.flags[0]=true
|
|
||||||
nem.flags[2]=true
|
|
||||||
for k,v in pairs(df.global.world.nemesis.all) do
|
|
||||||
if v.id==nem.id then
|
|
||||||
df.global.ui_advmode.player_id=k
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
error("Current unit does not have nemesis record, further working not guaranteed")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tools.menu:add("Change Adventurer",tools.change_adv)
|
|
||||||
|
|
||||||
function tools.MakeFollow(unit,trgunit)
|
|
||||||
|
|
||||||
if unit == nil then
|
|
||||||
unit=getCreature()
|
|
||||||
end
|
|
||||||
if unit== nil then
|
|
||||||
error("Invalid creature")
|
|
||||||
end
|
|
||||||
if trgunit==nil then
|
|
||||||
trgunit=df.global.world.units.active[0]
|
|
||||||
end
|
|
||||||
unit.relations.group_leader_id=trgunit.id
|
|
||||||
local u_nem=getNemesis(unit)
|
|
||||||
local t_nem=getNemesis(trgunit)
|
|
||||||
if u_nem then
|
|
||||||
u_nem.group_leader_id=t_nem.id
|
|
||||||
end
|
|
||||||
if t_nem and u_nem then
|
|
||||||
t_nem.companions:insert(#t_nem.companions,u_nem.id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tools.menu:add("Make creature follow",tools.MakeFollow)
|
|
||||||
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=getline();
|
|
||||||
|
|
||||||
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=getline()
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
print("Type which to change (q cancels):")
|
|
||||||
repeat
|
|
||||||
r=getline()
|
|
||||||
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=getline()
|
|
||||||
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.project(unit,trg)
|
|
||||||
if unit==nil then
|
|
||||||
unit=getCreatureAtPointer()
|
|
||||||
end
|
|
||||||
|
|
||||||
if unit==nil then
|
|
||||||
error("Failed to project unit. Unit not selected/valid")
|
|
||||||
end
|
|
||||||
-- todo: add projectile to world, point to unit, add flag to unit, add gen-ref to projectile.
|
|
||||||
local p=df.proj_unitst:new()
|
|
||||||
local startpos={x=unit.pos.x,y=unit.pos.y,z=unit.pos.z}
|
|
||||||
p.origin_pos=startpos
|
|
||||||
p.target_pos=trg
|
|
||||||
p.cur_pos=startpos
|
|
||||||
p.prev_pos=startpos
|
|
||||||
p.unit=unit
|
|
||||||
--- wtf stuff
|
|
||||||
p.unk14=100
|
|
||||||
p.unk16=-1
|
|
||||||
p.unk23=-1
|
|
||||||
p.fall_delay=5
|
|
||||||
p.fall_counter=5
|
|
||||||
p.collided=true
|
|
||||||
-- end wtf
|
|
||||||
local citem=df.global.world.proj_list
|
|
||||||
local maxid=1
|
|
||||||
local newlink=df.proj_list_link:new()
|
|
||||||
newlink.item=p
|
|
||||||
while citem.item~= nil do
|
|
||||||
if citem.item.id>maxid then maxid=citem.item.id end
|
|
||||||
if citem.next ~= nil then
|
|
||||||
citem=citem.next
|
|
||||||
else
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
p.id=maxid+1
|
|
||||||
newlink.prev=citem
|
|
||||||
citem.next=newlink
|
|
||||||
|
|
||||||
local proj_ref=df.general_ref_projectile:new()
|
|
||||||
proj_ref.projectile_id=p.id
|
|
||||||
unit.refs:insert(#unit.refs,proj_ref)
|
|
||||||
unit.flags1.projectile=true
|
|
||||||
end
|
|
||||||
function tools.empregnate(unit)
|
|
||||||
if unit==nil then
|
|
||||||
unit=getSelectedUnit()
|
|
||||||
end
|
|
||||||
|
|
||||||
if unit==nil then
|
|
||||||
unit=getCreatureAtPos(getxyz())
|
|
||||||
end
|
|
||||||
|
|
||||||
if unit==nil then
|
|
||||||
error("Failed to empregnate. Unit not selected/valid")
|
|
||||||
end
|
|
||||||
if unit.curse then
|
|
||||||
unit.curse.add_tags2.STERILE=false
|
|
||||||
end
|
|
||||||
local genes = unit.appearance.genes
|
|
||||||
if unit.relations.pregnancy_ptr == nil then
|
|
||||||
print("creating preg ptr.")
|
|
||||||
if false then
|
|
||||||
print(string.format("%x %x",df.sizeof(unit.relations:_field("pregnancy_ptr"))))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
unit.relations.pregnancy_ptr = { new = true, assign = genes }
|
|
||||||
end
|
|
||||||
local ngenes = unit.relations.pregnancy_ptr
|
|
||||||
if #ngenes.appearance ~= #genes.appearance or #ngenes.colors ~= #genes.colors then
|
|
||||||
print("Array sizes incorrect, fixing.")
|
|
||||||
ngenes:assign(genes);
|
|
||||||
end
|
|
||||||
print("Setting preg timer.")
|
|
||||||
unit.relations.pregnancy_timer=10
|
|
||||||
unit.relations.pregnancy_mystery=1
|
|
||||||
end
|
|
||||||
tools.menu:add("Empregnate",tools.empregnate)
|
|
||||||
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=getline()
|
|
||||||
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.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=getline()
|
|
||||||
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(getline())
|
|
||||||
print("enter x1:")
|
|
||||||
xe=tonumber(getline())
|
|
||||||
print("enter y0:")
|
|
||||||
ys=tonumber(getline())
|
|
||||||
print("enter y1:")
|
|
||||||
ye=tonumber(getline())
|
|
||||||
print("enter z0:")
|
|
||||||
zs=tonumber(getline())
|
|
||||||
print("enter z1:")
|
|
||||||
ze=tonumber(getline())
|
|
||||||
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,8 +0,0 @@
|
|||||||
if not(FILE) then
|
|
||||||
--tools.menu:add("Change site type",tools.changesite)
|
|
||||||
--tools.menu:add("Change site flags",tools.changeflags)
|
|
||||||
--tools.menu:add("Hostilate creature",tools.hostilate)
|
|
||||||
--tools.menu:add("Print current mouse block",tools.mouseBlock)
|
|
||||||
|
|
||||||
tools.menu:display()
|
|
||||||
end
|
|
@ -1 +0,0 @@
|
|||||||
as -anl --32 -o triggers.o triggers.asm
|
|
@ -1,20 +0,0 @@
|
|||||||
function func.Find_Print()
|
|
||||||
pos=offsets.find(offsets.base(),0x73,0x02,0x8b,0xce,0x53,0x6a,0x01,0x6a,0x06,CALL) -- a hack for now...
|
|
||||||
return engine.peekd(pos+10)+pos+14-offsets.base()
|
|
||||||
end
|
|
||||||
function func.PrintMessage(msg,color1,color2)
|
|
||||||
func.f_print_pos= func.f_print_pos or func.Find_Print()
|
|
||||||
print(string.format("Print @:%x",func.f_print_pos))
|
|
||||||
debuger.suspend()
|
|
||||||
d=NewCallTable() -- make a call table
|
|
||||||
t=Allocate(string.len(msg))
|
|
||||||
engine.pokestr(t,msg)
|
|
||||||
--print(string.format("Message location:%x",t))
|
|
||||||
d["ECX"]=t --set ecx to message location
|
|
||||||
d["STACK5"]=color1 -- push to stack color1
|
|
||||||
d["STACK4"]=color2 -- push to stack color2
|
|
||||||
d["STACK3"]=0 -- this is usually 0 maybe a struct pointing to location of this message?
|
|
||||||
PushFunction(func.f_print_pos+offsets.base(),d) -- prep to call function
|
|
||||||
-- was 0x27F030
|
|
||||||
debuger.resume()
|
|
||||||
end
|
|
@ -1,12 +0,0 @@
|
|||||||
func={}
|
|
||||||
dofile("dfusion/triggers/functions.lua")
|
|
||||||
func.menu=MakeMenu()
|
|
||||||
function func.PrintMessage_()
|
|
||||||
print("Type a message:")
|
|
||||||
msg=io.stdin:read()
|
|
||||||
func.PrintMessage(msg,6,1)
|
|
||||||
end
|
|
||||||
if not(FILE) then -- if not in script mode
|
|
||||||
func.menu:add("Print message",func.PrintMessage_)
|
|
||||||
func.menu:display()
|
|
||||||
end
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue