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