v50 Steam/Premium information for editors
  • v50 information can now be added to pages in the main namespace. v0.47 information can still be found in the DF2014 namespace. See here for more details on the new versioning policy.
  • Use this page to report any issues related to the migration.
This notice may be cached—the current version can be found here.

Difference between revisions of "Utility:DFusion"

From Dwarf Fortress Wiki
Jump to navigation Jump to search
Line 16: Line 16:
  
 
== Exported functions and objects ==
 
== Exported functions and objects ==
Objects differ from functions by calling convention ( using '':'' instead of '.'). Also most of the functions are grouped.
+
The DF is accessed by object 'df'. This object holds all the types, globals table and some helper functions.
=== Df memory object ===
+
=== Examples ===
In the new version there is a table called "df". It holds all the global objects of DF. To get list of fields available use 'printGlobals()'.
 
There are also helper functions 'printFields(object)' and 'addressOf(object,[field])'
 
Using new df object is very simple:
 
 
<pre>
 
<pre>
-- to get
+
first_unit=df.global.world.units.all[0] --gets first unit
print(df.window_x)
+
first_unit.name.first_name="Urist"
-- to set
 
df.window_x=1
 
 
</pre>
 
</pre>
Some objects returned are more complex:
+
You can iterate in all the objects:
 
<pre>
 
<pre>
--most complex object (afaik)
+
for k,v in pairs(df.global.world.units.all) do --gets ALL the units
printFields(df.world)
+
  v.name.first_name="Urist" --now everyone will be called URIST!!
 +
end
 
</pre>
 
</pre>
At first it will be confusing, but worry not, there is a tool (dfusion->editor) that lets you edit df without writing lua code.
+
This is also useful to get what fields are available:
 
 
Some notes:
 
Sometimes returned object is a pointer, than you need to dereference it:
 
 
<pre>
 
<pre>
-- this gets first unit, but it's a pointer, so dereference it
+
for k,v in pairs(df.global) do --any object can be instead of df.global
df.world.units.all[0]:deref().pos.x=0
+
  print(k)
-- also as you can see 'all' is a vector (or an array) so you can access it's members by numbers. This works on flags too.
+
end
 
</pre>
 
</pre>
 
+
Also all the flags can be accessed by name or by number:
=== Dfhack/DF interface ===
+
<pre>
These functions are sown into dfhack or modifies DF directly
+
first_unit.flags.dead=true --is same as...
 +
first_unit.flags[1]=true --... this
 +
</pre>
 +
=== Other objects ===
 
==== Console. ====
 
==== Console. ====
 
{| class="wikitable"
 
{| class="wikitable"

Revision as of 08:03, 31 March 2012

DFusion info page

Thread for discussions: Thread

Usage

Dfusion plugin offers four DFhack commands: 'dfusion', 'dfuse' and 'lua', 'runlua'.

lua

Runs an interactive lua console. For more on lua commands see Lua reference manual or google "lua". Also this command could be ran with filepath as an argument. Then it runs that file as a lua script file. E.g. lua dfusion/temp.lua runs a file <your df path>/dfusion/temp.lua.

runlua

Similar to lua <filename> but not interactive, to be used with hotkeys

dfusion

First this command runs all plugins' init.lua part then show a menu. Type number to run specified plugin.

dfuse

Similar to dfusion but not interactive. To be used with hotkeys (later will have command support).


Also dfuse/dfusion runs an init script located at 'save directory/dfusion/init.lua'. And 'initcustom.lua' if it exists

Exported functions and objects

The DF is accessed by object 'df'. This object holds all the types, globals table and some helper functions.

Examples

first_unit=df.global.world.units.all[0] --gets first unit
first_unit.name.first_name="Urist"

You can iterate in all the objects:

for k,v in pairs(df.global.world.units.all) do --gets ALL the units
   v.name.first_name="Urist" --now everyone will be called URIST!!
end

This is also useful to get what fields are available:

for k,v in pairs(df.global) do --any object can be instead of df.global
   print(k)
end

Also all the flags can be accessed by name or by number:

first_unit.flags.dead=true --is same as...
first_unit.flags[1]=true --... this

Other objects

Console.

name description example
print prints a message to dfhack console Console.print("Hello world!")
printerr prints an error message to dfhack console Console.printerr("Error world!")
clear clears console Console.clear()
color sets text color Console.color(2)
reset_color resets text color to defaults Console.reset_color()
cursor sets if the cursor should be visible Console.cursor(true)
msleep waits for x milliseconds Console.msleep(200)
get_columns returns number of columns in the console Console.get_columns()
get_rows returns number of rows in the console Console.get_rows()
lineedit asks user for input Console.lineedit("Type in your name:")

Process.

VersionInfo.

engine.

name description example
peek(b\w\d) reads byte\word\double word from memory peekb(0x15486)
peekarb reads a chunk of memory peekarb(0x15486,100) -- reads 100 bytes from 0x15486
peekstr reads a string from memory peekstr(0x15486)
poke(b\w\d) writes byte\word\double word to memory peekb(0x15486,100)
pokearb writes a chunk of memory (gotten with peekarb) pokearb(0x15486,data,100) -- writes 100 bytes from data to 0x15486
pokestr writes a string to memory peekstr(0x15486,"Hello world")

FunctionCall.

name description example
call(f_ptr,calling_convention,arguments...) calls a function from df. Supports up to 7 arguments. Danger: this could (and probably will) crash df if used incorrectly. FunctionCall.call(somepointertofunction,FunctionCall.THIS_CALL,thisptr)
THIS_CALL a numeric constant for function calling convention. -
STD_CALL -"- -
FAST_CALL -"- -
CDECL_CALL -"- -

From scripts

These commands are exported from script files. Most of them are in "common.lua" file.

Patterns

DEPRECATED use types[<tname>] or directly df.<subitem>

How to

This section explains in detail some of more complex things that could be done with dfusion.

OnFunction

There are two parts to OnFunction: adding new triggers and using already existing triggers. To add new trigger you must know exact location of function call (and what it does) also it would help a lot if you know what registers correspond to what data. Usually this could be worked out by analysing call stack after setting a data breakpoint (watch in GDB) and then guessing what does what. Using already existing triggers is way simpler. Adding a callback (a function to be called when a trigger is encountered) is done by onfunction.SetCallback(name,function). For possible names see locations.lua (at the time of writing there is "Move" and "Die" both in Linux and Windows). Possible use of it:

function DeathMsg(values)
	local name
	name=engine.peek(values[onfunction.hints["Die"].creature],ptt_dfstring)
	print(name:getval().." died")
end
onfunction.SetCallback("Die",DeathMsg)

In this example we bind 'DeathMsg' function to "Die" trigger. Values argument has all the registers and a return address. So we lookup from witch register do we need to read the creature pointer ( values[onfunction.hints["Die"].creature ) and read a string just from the beginning (usually the creature starts with his name). Then print it to the console.

Note: there can be only one callback per trigger. Also if you know any more trigger locations please share :)

Tips and Tricks

  • To use dfusion's functionality in lua first run dfusion (exit it with 'q') and then use run lua