Undocumented functions, documented

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
Post Reply
minmay
Posts: 2780
Joined: Mon Sep 23, 2013 2:24 am

Undocumented functions, documented

Post by minmay »

How:

Code: Select all

do
local doneTables = {}
local function spaces(indentLevel)
  local rval = ""
  for i=1,indentLevel do
    rval=rval.."  "
  end
  return rval
end
local function printTable(name,t,recurseLevel)
  doneTables[t] = true
  print(string.format("%s%s = table:",spaces(recurseLevel or 0),name))
  recurseLevel = recurseLevel or 1
  for key,value in pairs(t) do
    if type(value) == "table" then
	  if doneTables[t] then
        print(string.format("%s%s = table: %s",spaces(recurseLevel),tostring(key),tostring(value)))
      else
        printTable(key,value,recurseLevel+1)
      end
    else
      print(string.format("%s%s = %s",spaces(recurseLevel),tostring(key),tostring(value)))
    end
  end
end
printTable("Config",Config)
printTable("Console",Console)
printTable("DamageFlags",DamageFlags)
printTable("Dungeon",Dungeon)
printTable("Editor",Editor)
printTable("GameMode",GameMode)
printTable("ItemSlot",ItemSlot)
printTable("MersenneTwister",MersenneTwister)
printTable("Time",Time)
printTable("math",math)
printTable("string",string)
printTable("table",table)
end
Result:

Code: Select all

Config = table:
  getRenderingQuality = function: 0x00e91d68
  getKeyBinding = function: 0x00e91b70
Console = table:
  setSuppressWarnings = function: 0x00e91978
  warn = function: 0x00e91780
DamageFlags = table:
  NoLingeringEffects = 512
  Champion2 = 8
  HalveBackRowDamage = 128
  OngoingDamage = 2
  Champion1 = 4
  Champion4 = 32
  Impact = 1
  DamageSourceIceShards = 1024
  Champion3 = 16
  IgnoreImmunities = 64
  CameraShake = 256
Dungeon = table:
  getMaxLevels = function: 0x00e92740
  getMap = function: 0x00e92548
Editor = table:
  isRunning = function: 0x00e92938
GameMode = table:
  getGameFlag = function: 0x00e938f8
  setEnableControls = function: 0x00e93ee0
  setCamera = function: 0x00e92d28
  showImage = function: 0x00e94ab0
  getEnableControls = function: 0x00e93ce8
  completeGame = function: 0x00e95098
  setTimeMultiplier = function: 0x00e942d0
  playStream = function: 0x00e94ca8
  getStatistic = function: 0x00e944c8
  getTimeMultiplier = function: 0x00e940d8
  setMaxStatistic = function: 0x00e948b8
  advanceTime = function: 0x00e93310
  playVideo = function: 0x00e94ea0
  fadeIn = function: 0x00e93118
  fadeOut = function: 0x00e92f20
  unlockAchievement = function: 0x00e92b30
  getMaxStatistic = function: 0x00e946c0
  setTimeOfDay = function: 0x00e93700
  setGameFlag = function: 0x00e93af0
  getTimeOfDay = function: 0x00e93508
ItemSlot = table:
  OffHand2 = 12
  Feet = 6
  BackpackLast = 32
  Weapon2 = 11
  Weapon = 1
  Gloves = 9
  Necklace = 8
  MaxSlots = 32
  Chest = 4
  Head = 3
  Bracers = 10
  Legs = 5
  OffHand = 2
  Cloak = 7
  BackpackFirst = 13
MersenneTwister = table:
  __gc = function: 0x00356e48
  baseclass = table: table: 0x00351998
  dispose = function: 0x00356e68
  isDisposed = function: 0x00356df0
  create = function: 0x0035c968
  properties = table: table: 0x0035c9e8
  __tostring = function: 0x00356e28
  type = MersenneTwister
  randomInt = function: 0x0035c9a8
  random = function: 0x0035c988
  __index = table: table: 0x0035c940
Time = table:
  systemTime = function: 0x00e91f60
  deltaTime = function: 0x00e92158
  currentTime = function: 0x00e92350
math = table:
  ceil = function: fast#39
  tan = function: fast#46
  smoothstep = function: 0x00354f70
  log10 = function: fast#42
  sign = function: 0x00392bf0
  sinh = function: fast#50
  chromacity = function: 0x00354fe8
  ldexp = function: fast#60
  huge = inf
  atan2 = function: fast#57
  min = function: fast#61
  fmod = function: fast#59
  exp = function: fast#43
  random = function: 0x0035ca10
  rad = function: fast#56
  log = function: fast#41
  map = function: 0x00354f88
  cos = function: fast#45
  clamp = function: 0x00354f40
  saturation = function: 0x00355000
  mod = function: fast#59
  nextPow2 = function: 0x00354fb8
  luminance = function: 0x00354fd0
  isPow2 = function: 0x00354fa0
  randomseed = function: 0x0035ca30
  floor = function: fast#38
  sqrt = function: fast#40
  max = function: fast#62
  atan = function: fast#49
  noise = function: 0x00396238
  acos = function: fast#48
  lerp = function: 0x00354f58
  abs = function: fast#37
  sqr = function: 0x00392bd8
  sin = function: fast#44
  asin = function: fast#47
  frexp = function: fast#53
  tanh = function: fast#52
  cosh = function: fast#51
  modf = function: fast#54
  pow = function: fast#58
  deg = function: fast#55
  pi = 3.1415926535898
string = table:
  find = function: fast#86
  capitalize = function: 0x00355048
  camelCaseToUnderscore = function: 0x00355060
  len = function: fast#77
  gsub = function: fast#90
  upper = function: fast#84
  sub = function: fast#80
  char = function: fast#79
  split = function: 0x00355030
  rep = function: fast#81
  underscoreToCamelCase = function: 0x00355078
  lower = function: fast#83
  gmatch = function: fast#89
  reverse = function: fast#82
  byte = function: fast#78
  match = function: fast#87
  count = function: 0x00355018
  gfind = function: fast#89
  format = function: fast#91
table = table:
  sort = function: fast#99
  keys = function: 0x003550c0
  copy = function: 0x00355090
  erase = function: 0x00355120
  contains = function: 0x00355108
  indexOf = function: 0x003550f0
  values = function: 0x003550d8
  foreach = function: fast#93
  maxn = function: fast#95
  remove = function: fast#97
  foreachi = function: fast#92
  deepcopy = function: 0x003550a8
  getn = function: fast#94
  concat = function: fast#98
  insert = function: fast#96
User scripts can freely overwrite these values if they like. Want to change the result of multiplying two vectors, even when it happens internally? You can! I don't recommend it though. Remember that such a change won't be serialized, so you need to do it every time the game is reloaded (easy to do in an init file).

Here are the ones you didn't know about:
GameMode.getEnableControls(), GameMode.setEnableControls(boolean)
Seems extremely similar to
GameMode.setGameFlag("DisableMovement",true)
GameMode.setGameFlag("DisableMouseLook",true)
GameMode.setGameFlag("DisableKeyboardShortcuts",true)
but with a few differences: you can't pick up or throw items with the mouse, you can't open or close champion windows (but if you open a champion window before disabling controls, you can still manipulate items inside the champion window, switch tabs, train skills, etc.), but you can still attack and swap weapon sets with the mouse. Seems safe enough, provided you always remember to enable the controls again when you're done.

GameMode.getTimeMultiplier(), GameMode.setTimeMultiplier(number)
Remember when I guessed that Grimrock 2 probably has a timescale variable, but I didn't know of a way to change it without memory editing? Well, I wasn't lying, I actually didn't know about GameMode.setTimeMultiplier() at the time. But before you add your Time Slow spell, keep in mind that changing timescale in games generally breaks all manner of things, and that may be the reason this function isn't listed in the scripting reference.

math.atan2(number,number)
http://www.cplusplus.com/reference/cmath/atan2/

math.chromacity(vector)
Doesn't work from the user scripting interface, and to be honest, I have no idea what the hell you'd use chromacity for in the first place.

math.clamp(number num,number min,number max)
Returns the equivalent of math.max(min,math.min(max,num)). Note the order of the parameters to math.min and math.max is relevant if you pass in NaN (this is also how I am able to figure it out).

math.cosh

math.isPow2(number)
Returns true if the number is a non-negative integer power of 2, false otherwise.

math.frexp(number)
Returns the significant and exponent of the number (remember, every number in Lua 5.1 is a binary64 floating point). This is actually extremely useful in certain extremely specific situations.

math.ldexp(number num,number exponent)
Returns num*2^exponent.

math.lerp(number a,number b,number c)
math.lerp(vector a,vector b,number c)
math.lerp(matrix a,matrix b,number c)

Returns the linear interpolation of a and b, with c as the "time" - that is, at 0 it returns a, at 1 it returns b, at 0.5 it returns the average of a and b.

math.log10(number)
Returns the logarithm base 10 of the number. I probably didn't need to say that.

math.luminance(vector)
Treats the vector as a color and returns the luminance.

math.map
I honestly have no clue what this does, other than it seems to want numbers or maybe vectors as arguments.

math.nextPow2(number)
Returns the smallest power of 2 that is greater than or equal to the number. Returns 1 if you pass NaN, in case you needed to know that for some insane reason.

math.noise(number)
Returns a number between -0.5 and 0.5, which is the result of a mysterious mostly-smooth function that seems to have a very long period. Note that this function frequently returns 0. Used widely for flickering lights.

math.pow(number x, number e)
Returns x^e, but is slower than just typing x^e, and doesn't work on vectors...

math.saturation(vector,number)
Used in the asset pack. Treats the vector as a color, and returns a vector representing that color with its saturation multiplied by the number. E.g. math.saturation(vec(1,0.5,0),0.8) returns vec(0.918480, 0.518480, 0.118480, 0.000000), and math.saturation(vec(1,0.5,0),0) returns vec(0.592400, 0.592400, 0.592400, 0.000000). Should you give a saturation value greater than 1, the returned vector can include negative numbers.

math.sign(number)
Returns 1 if number is positive, -1 if number is negative, 0 if number is 0 or NaN.

math.sinh(number)

math.smoothstep(number x, number left, number right)
See https://en.wikipedia.org/wiki/Smoothstep, but note the arguments are in a different order than on that page; x is the first argument instead of the last. Seems like it *should* work on vectors but I always get a stack overflow when I try.

math.sqr(number)
math.sqr(vector)

Returns the square of the argument. Useless for numbers (using the ^ or * operator is many times faster than making a function call) but nice to have for vectors.

math.tanh(number)

MersenneTwister stuff
There's really not much of a reason to mess with any of the undocumented fields on this table, unless you just want to cause a crash.

string.camelCaseToUnderscore(string)
("CamelCase DUCK"):camelCaseToUnderscore() returns "camel_case _d_u_c_k".

string.capitalize(string)
Capitalizes the first letter. ("look out! it's a DUCK"):capitalize() returns "Look out! it's a DUCK".

string.count(string str, string search)
Returns the number of times str contains search.
("duckDUCKduckDUCK"):count("duck") returns 2.
If search is the empty string, enters an infinite loop, so don't do that.

string.gfind
The lua wiki doesn't list this on the string library tutorial page for some reason, but it is a standard Lua library function:
http://www.lua.org/pil/20.1.html

string.split(string str, string delimiter)
Returns a table which is str "split" by delimiter.
("123456DUCK789DUCK0123"):split("DUCK") returns {"123456","789","0123"}.
("cat"):split("DUCK") returns {"cat"}.
If delimiter is the empty string, enters an infinite loop, so don't do that.

string.underscoreToCamelCase(string)
("duck_duck_DUCK_duck"):underscoreToCamelCase() returns "duckDuckDUCKDuck".

table.erase(table)
Assigns nil to all keys in the table, turning it into an empty table.

table.contains(table array,object)
Returns true if any of the values in the array are equal to the object, false otherwise. ONLY WORKS ON ARRAYS (tables with consecutive integer keys). Very useful, but remember that this is an O(n) operation.

table.copy(table)
Returns a shallow copy of the table, including the metatable.

table.deepcopy(table)
Returns a "deep" copy of the table, including the metatable. Copying a GameObject, component, Champion, or pretty much anything else that isn't a simple table will produce a bad object that can't be used for anything useful (won't be added to the map and no methods can be used). However, it works for copying matrices and vectors. But keep in mind that GameObject:getWorldPosition() and GameObject:getWorldRotation() already return copies of the vector and matrix.

table.indexOf(table,object)
If any of the values in the array are equal to the object, returns its index, otherwise returns nil. ONLY WORKS ON ARRAYS (tables with consecutive integer keys). Very useful, but remember that this is an O(n) operation.

table.keys(table)
Returns an array of all the keys in the table.

table.values(table)
Returns an array of all the values in the table. Wanted to use table.contains() on a non-array table? If you aren't concerned about performance, you can use table.contains(table.values(tab),object). Of course, the array returned will be unsorted (except for the part of the table that was already an array, if any), so table.indexOf(table.values(tab),object) is not useful.

Set(array)
This global function is equivalent to

Code: Select all

function set(array)
  local rval = {}
  for _,v in ipairs(array) do
    rval[v]=true
  end
  return rval
end
vec.__add(vector,vector) or + operator
Adds two vectors together.

vec.__div(vector,number) or / operator
Divides a vector by a scalar. You cannot divide a vector by another vector, and will get a stack overflow if you try.

vec.__index(table,key) or table indexing operator
vec.__newindex(table,key) or assignment operator
The default vec.__index and vec.__newindex make vec.x equivalent to vec[1], vec.y equivalent to vec[2], etc. The default __newindex will raise an error if you try to assign to an index other than 1, 2, 3, 4, "x", "y", "z", or "w".

vec.__mul(vector,vector or number) or * operator
Multiplies two vectors, or multiplies a vector by a number.

vec.sphericalDirection(number azimuthal,number polar)
Returns a vector pointing in the direction indicated by the passed azimuthal and polar angles (both numbers). Example: vec.sphericalDirection(math.pi/2,math.pi/4) will return vec(0,sqrt(2)/2,sqrt(2)/2).

vec.__sub(vector,vector) or binary - operator
Subtracts one vector from another.

vec.__tostring(vector)
Returns the string representation of the vector (what you get when you use the "print" function to print a vector).

vec.__unm(vector) or unary - operator
Returns the unary minus of the vector.

vec.clone(vector)
Returns a copy of the vector.

vec.cross(vector,vector)
Returns the 3D cross product of two vectors (4th dimension is ignored)

vec.dot(vector,vector)
Returns the dot product of two vectors.

vec.isvec(any)
Returns whether the argument is a vector. Since the global type() function can't differentiate between vectors and tables, this is by far the most convenient way to ensure a value is a vector.

vec.length(vector)
Returns the length of a vector, i.e., sqrt(vector[1]^2+vector[2]^2+vector[3]^2+vector[4]^2).

vec.length3(vector)
Returns the length of the vector ignoring the 4th value, so vec.length3(vec(2,2,2,2)) is the same as vec.length(vec(2,2,2,0)).
FUN FACT: This function is used internally by MonsterWarpComponent's visual effect and absolutely nothing else, so you can change this function to mess with the warp effect without breaking anything else.

vec.lengthSquared(vector)
Like length without the sqrt.

vec.lengthSquared3(vector)
Like length3 without the sqrt.

vec.normalize(vector)
Normalizes a vector.

vec.perpendicular(vector)
Returns a vector that is perpendicular to the argument. Assumes the vector is 3D, so the fourth element is ignored and vec.perpendicular(vec(0,1)) returns vec(0,-0,1)

vec.set(vector a,vector b)
Copies the contents of vector b to vector a.

vec.truncate(vector,number length)
Returns a copy of the vector that is truncated so its length does not exceed length. If the vector's length is already at or below length, the copy is identical to the original vector.
Last edited by minmay on Sat Oct 08, 2016 2:34 am, edited 4 times in total.
Grimrock 1 dungeon
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
User avatar
petri
Posts: 1917
Joined: Thu Mar 01, 2012 4:58 pm
Location: Finland

Re: Undocumented functions, documented

Post by petri »

math.map(x, a, b, c, d) maps 'x' from range [a,b] to range [c,d].

Oh and thanks for the bug reports regarding string.count() and string.split() (Sloppy coding...) I'll fix them in the codebase for future projects.
User avatar
Drakkan
Posts: 1318
Joined: Mon Dec 31, 2012 12:25 am

Re: Undocumented functions, documented

Post by Drakkan »

petri wrote:math.map(x, a, b, c, d) maps 'x' from range [a,b] to range [c,d].

Oh and thanks for the bug reports regarding string.count() and string.split() (Sloppy coding...) I'll fix them in the codebase for future projects.
future projects. LOG 3 is REAL ;) :d
Breath from the unpromising waters.
Eye of the Atlantis
User avatar
akroma222
Posts: 1029
Joined: Thu Oct 04, 2012 10:08 am

Re: Undocumented functions, documented

Post by akroma222 »

This is brilliant minmay :D
Thankyou for posted this, very helpful!!
User avatar
Eleven Warrior
Posts: 745
Joined: Thu Apr 18, 2013 2:32 pm
Location: Australia

Re: Undocumented functions, documented

Post by Eleven Warrior »

Good job Min :) Is there a command that stops the player attacking, throwing items and casting man? I saw this command but sure how to implement it: GameMode.getEnableControls(), GameMode.setEnableControls(boolean)

I know how to stop the party and mouse but not sure how to do the above. Thxs if it's possible Min :)
vieuxchat
Posts: 48
Joined: Wed Mar 02, 2016 3:14 pm

Re: Undocumented functions, documented

Post by vieuxchat »

Would creating connectors with a function that only returns false work with the onAttack and onCastSpell hooks from partyComponent ?
minmay
Posts: 2780
Joined: Mon Sep 23, 2013 2:24 am

Re: Undocumented functions, documented

Post by minmay »

Updated for vec and the global Set function.
Grimrock 1 dungeon
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
Post Reply