Mod Tool/Scripting
< Mod Tool
General
logmessage license logmessage version ' examples: ' INFO : Softimage ' INFO : 13.0.114.0 ' INFO : Mod Tool ' INFO : 7.5.203.0
logmessage XSIUtils.ResolvePath("$XSI_USERHOME/")
' directory to addons and exported resources
logmessage XSIUtils.ResolvePath("$XSI_HOME/")
' directory to a few imported core files that must be modified (Model.vbs, ModStartup.js, ...)
' example:
' INFO : C:\Users\Paradox-01\Autodesk\Softimage_2015\
' INFO : C:\Program Files\Autodesk\Softimage 2015\
' INFO : C:\Users\Paradox-01\Autodesk\Softimage_Mod_Tool_7.5\
' INFO : C:\Softimage\Softimage_Mod_Tool_7.5\
logmessage XSIUtils.ResolvePath("$XSI_CPU/")
' shows programm bit version
' example:
' for 64-bit
' INFO : nt-x86-64\
' for 32-bit
' INFO : nt-x86\
Build an vbs executable
Executable, app(lication), program. Whatever you call it, sometimes it might be necessary to compile the script into an actual program.
Even though vbs is a script language and not a programming language, it can be done.
VbsEdit is an editor to fulfill such task with ease.
- Just goto File > Convert into Executable. Choose output path, 32/64-bit version and hit OK.
OS bit version
if GetObject("winmgmts:root\cimv2:Win32_Processor='cpu0'").AddressWidth = 64 then
logmessage "64"
else
logmessage "32"
end if
faster
Set WshShell = CreateObject("WScript.Shell")
if instr(WshShell.RegRead("HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0\Identifier"), "x86") = 1 then
logmessage "32"
else
logmessage "64"
end if
Read registry
Mod Tool (because 32-bit) fails to execute following code properly on 64-bit operation systems. So the code must be build as 64-bit and 32-bit application.
Set WshShell = CreateObject("WScript.Shell")
AE_path = WshShell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{B67333BB-1CF9-4EFD-A40B-E25B5CB4C8A7}}_is1\InstallLocation")
MsgBox AE_path
Dim fso
Set fso = CreateObject ("Scripting.FileSystemObject")
txt_location = fso.GetAbsolutePathName(".") & "\AE_path.txt"
Set wText = fso.CreateTextFile (txt_location, 1)
wText.WriteLine AE_path
wText.Close
Read file
Binary
scan_AKEV_file_table
sub scan_AKEV_file_table
' ##############################################
OniInputFile = "H:\Oni\AE\GameDataFolder\level1_Final\AKEVEnvWarehouse.oni"
' ##############################################
Set OniInputFileStream = CreateObject("ADODB.Stream")
OniInputFileStream.Type = 1
OniInputFileStream.Open
OniInputFileStream.LoadFromFile OniInputFile
' ### read AKEV textures table offset and size
ByteNum = 4
' ##############################################
TOffset = cLng("&H" & "28")
' ##############################################
OniInputFileStream.Position = TOffset
BArr1 = OniInputFileStream.Read(ByteNum)
ByteNum = 4
' ##############################################
TSize = cLng ("&H" & "2C")
' ##############################################
OniInputFileStream.Position = TSize
BArr2 = OniInputFileStream.Read(ByteNum)
' ### get AKEV textures table offset and size
TOffsetHex = SimpleBinaryToString(BArr1)
for i = ubound(TOffsetHex ) - 1 to 0 step -1
newhex = newhex & hex(Asc(TOffsetHex(i)))
next
logmessage newhex
logmessage "name table offset: " & cLng("&H" & newhex)
TOffsetInt = cLng("&H" & newhex)
newhex = ""
TSizeHex = SimpleBinaryToString(BArr2)
for i = ubound(TSizeHex) - 1 to 0 step -1
newhex = newhex & hex(Asc(TSizeHex(i)))
next
logmessage newhex
logmessage "name table size: " & cLng("&H" & newhex)
TSizeInt = cLng("&H" & newhex)
logmessage "------------------------------"
' ### read table content
ByteNum = TSizeInt
OniInputFileStream.Position = TOffsetInt
BArr3 = OniInputFileStream.Read(ByteNum)
TContent = SimpleBinaryToString(BArr3)
' ### name grapper
NG = ""
for each n in TContent
if not Asc(n) = 0 then
NG = NG & n
else
'if instr(NG, "TXMP") = 1 then
' write TXMP to array ?
logmessage NG
'end if
NG = ""
end if
next
end sub
Function SimpleBinaryToString(Binary)
ReDim tmpArr(LenB(Binary) - 1)
For I = 1 To LenB(Binary)
S = Chr(AscB(MidB(Binary, I, 1)))
tmpArr(I - 1) = S
Next
SimpleBinaryToString = tmpArr
End Function
Output:
' INFO : 0E40 ' INFO : name table offset: 3648 ' INFO : 0A4A ' INFO : name table size: 2634 ' INFO : ------------------------------ ' INFO : AKEVEnvWarehouse ' INFO : AGDBEnvWarehouse ' INFO : TXMP_DOOR_FRAME ' INFO : TXMPNONE ' INFO : TXMPSUMI_1 ' INFO : TXMPTC_CONTROL_01 ' [...] ' INFO : TXMPWH_DCTRBND
Modify file
Binary
Change FilePath and in case of binary patching use function "StringToByteArray".
FilePath = "C:\path_to\AKEVEnvWarehouse.oni"
' ### create stream objects
Set InputStream = CreateObject("ADODB.Stream")
InputStream.Type = 1
InputStream.Open
Set OutputStream = CreateObject("ADODB.Stream")
OutputStream.Type = 1
OutputStream.Open
' ### load input stream from file
InputStream.LoadFromFile FilePath
' ### copy first 16 signs of input stream to output stream
OutputStream.Write InputStream.Read(16)
' ### apply patch
' # ASCII patching
patch_data = "ABCD"
patch_data_length = len(patch_data)
' patch_data_length = 4
InputStream.Position = InputStream.Position + patch_data_length
OutputStream.Write CreateObject("System.Text.ASCIIEncoding").GetBytes_4(patch_data)
' # binary patching
'OutputStream.Write StringToByteArray("41424344")
' ### re-add data that was cut off
OutputStream.Write InputStream.Read
' ### unloader
InputStream.Close
Set InputStream = Nothing
' ### modes: 2 = overwrite; 1 = dontoverwrite
' test: save to new file
' FilePath2 = "C:\path_to\AKEVEnvWarehouseB.oni"
OutputStream.SaveToFile FilePath, 2
OutputStream.Close
Set OutputStream = Nothing
Conversions
String -> byte array
function StringToByteArray(ThisString)
for i = 1 To Len(ThisString) Step 2
str = str & Chr("&h" & Mid(ThisString, i, 2))
next
Set stream = CreateObject("ADODB.Stream")
With stream
.Open
.CharSet = "Windows-1252"
.Type = 2
' ### 2 = text
.WriteText str
.Position = 0
.Type = 1
' ### 1 = binary
StringToByteArray = .Read
.Close
End With
end function
' ### usage
ByteArray = StringToByteArray(ThisString)
Byte array -> string
Function ByteArrayToString(Binary) 'Antonin Foller, http://www.motobit.com 'Optimized version of a simple BinaryToString algorithm. Dim cl1, cl2, cl3, pl1, pl2, pl3 Dim L cl1 = 1 cl2 = 1 cl3 = 1 L = LenB(Binary) Do While cl1<=L pl3 = pl3 & Chr(AscB(MidB(Binary,cl1,1))) cl1 = cl1 + 1 cl3 = cl3 + 1 If cl3>300 Then pl2 = pl2 & pl3 pl3 = "" cl3 = 1 cl2 = cl2 + 1 If cl2>200 Then pl1 = pl1 & pl2 pl2 = "" cl2 = 1 End If End If Loop BinaryToString = pl1 & pl2 & pl3 End Function ' ### usage MyString = ByteArrayToString(ByteArray)
Math
Euler rotation -> matrix
function cosn (n) cosn = cos(XSIMath.DegreesToRadians(n)) end function function sinn (n) sinn = sin(XSIMath.DegreesToRadians(n)) end function ' ################ logmessage "input" x = 60 : logmessage x y = 60 : logmessage y z = 60 : logmessage z logmessage "##################" logmessage "converted" set RotMatX = XSIMath.CreateMatrix3(1, 0, 0, 0, cosn(x), sinn(x), 0, -sinn(x), cosn(x)) set RotMatY = XSIMath.CreateMatrix3(cosn(y), 0, -sinn(y), 0, 1, 0, sinn(y), 0, cosn(y)) set RotMatZ = XSIMath.CreateMatrix3(cosn(z), sinn(z), 0, -sinn(z), cosn(z), 0, 0, 0, 1) RotMatZ.MulInPlace RotMatY RotMatZ.MulInPlace RotMatX for i=0 to 2 for j=0 to 2 logmessage RotMatZ (i, j) next next ' INFO : input ' INFO : 60 ' INFO : 60 ' INFO : 60 ' INFO : ################## ' INFO : converted ' INFO : 0,25 ' INFO : 0,808012701892219 ' INFO : 0,53349364905389 ' INFO : -0,433012701892219 ' INFO : -0,399519052838329 ' INFO : 0,808012701892219 ' INFO : 0,866025403784439 ' INFO : -0,433012701892219 ' INFO : 0,25
Matrix -> Euler rotation
Function Atan2(y, x)
If x > 0 Then
Atan2 = Atn(y / x)
ElseIf x < 0 Then
Atan2 = Sgn(y) * (XSIMath.PI - Atn(Abs(y / x)))
ElseIf y = 0 Then
Atan2 = 0
Else
Atan2 = Sgn(y) * XSIMath.PI / 2
End If
End Function
function ToEuler(M00, M10, M20, M21, M22)
a = M00
b = M10
dim c, s, r
if b = 0 then
c = Sgn(a)
s = 0
r = Abs(a)
elseif a = 0 then
c = 0
s = Sgn(b)
r = Abs(b)
elseif Abs(b) > Abs(a) then
t = a / b
u = Sgn(b) * Sqr(1 + t * t)
s = 1 / u
c = s * t
r = b * u
else
t = b / a
u = Sgn(a) * Sqr(1 + t * t)
c = 1 / u
s = c * t
r = a * u
end if
Z = -Atan2(s, c)
Y = Atan2(M20, r)
X = -Atan2(M21, M22)
X = XSIMath.RadiansToDegrees(X)
Y = XSIMath.RadiansToDegrees(Y)
Z = XSIMath.RadiansToDegrees(Z)
ToEuler = array(X, Y, Z)
end function
' ################################
set RotMat = XSIMath.CreateMatrix3( _
0.25, 0.808012701892219, 0.53349364905389, _
-0.433012701892219, -0.399519052838329, 0.808012701892219, _
0.866025403784439, -0.433012701892219, 0.25 )
' convert matrix to euler rotation and store values to array
ReXYZ = ToEuler(RotMat(0,0), RotMat(1,0), RotMat(2,0), RotMat(2,1), RotMat(2,2))
logmessage "reconverted"
logmessage ReXYZ(0)
logmessage ReXYZ(1)
logmessage ReXYZ(2)
' INFO : 60
' INFO : 60
' INFO : 60
Euler rotation -> quaternion
dim x, y, z, dRotation, qRotation x = 90 y = 0 z = 0 set dRotation = XSIMath.CreateRotation(XSIMath.DegreesToRadians(x), XSIMath.DegreesToRadians(y), XSIMath.DegreesToRadians(z)) set qRotation = XSIMath.CreateQuaternion() dRotation.GetQuaternion (qRotation) LogMessage qRotation.W LogMessage qRotation.X LogMessage qRotation.Y LogMessage qRotation.Z ' INFO : 0,707106781186548 ' INFO : 0,707106781186547 ' INFO : 0 ' INFO : 0 ' to calculate oni quaternions from euler rotations use this setup: ' LogMessage qRotation.X ' LogMessage qRotation.Y ' LogMessage qRotation.Z ' LogMessage qRotation.W * -1
Quaternion -> Euler rotation
dim qW, qX, qY, qZ, qRotation, x, y, z qW = 0.707106781186548 qX = 0.707106781186547 qY = 0 qZ = 0 set qRotation = XSIMath.CreateQuaternion (qW, qX , qY, qZ) qRotation.GetXYZAngleValues x, y, z logmessage XSIMath.RadiansToDegrees(x) logmessage XSIMath.RadiansToDegrees(y) logmessage XSIMath.RadiansToDegrees(z) ' INFO : 89,9999999999999 ' INFO : 0 ' INFO : 0 ' to calculate euler rotations from oni quaternions use this setup: 'qX = ... 'qY = ... 'qZ = ... 'qW = ... * -1 'set qRotation = XSIMath.CreateQuaternion (qW, qX, qY, qZ)
Property Page
Detect a PPG
set oRoot = ActiveProject.ActiveScene.Root
if typename(oRoot.Properties("my_PPG")) = "Nothing" then
logmessage "couldn't find my_PPG"
else
logmessage "found my_PPG"
end if
Build a PPG
' general PPG setup
set oPSet = ActiveSceneRoot.AddProperty("CustomProperty", false, "my_PPG")
set oPPGLayout = oPSet.PPGLayout
' PPG content
' [...]
' open PPG
InspectObj oPSet
PPG content
Droplist
oPSet.AddParameter3 "Team", siString, 0 aListTeams = Array( "Konoko", 0, _ "TCTF", 1, _ "Syndicate", 2, _ "Neutral", 3, _ "SecurityGuard", 4, _ "RogueKonoko", 5, _ "Switzerland (is melee-immune)", 6, _ "SyndicateAccessory", 7 ) oPPGLayout.AddEnumControl "Team", aListTeams, "", siControlCombo
Radio options
oPSet.AddParameter3 "Team", siString, 0 aListTeams = Array( "Konoko", 0, _ "TCTF", 1, _ "Syndicate", 2, _ "Neutral", 3, _ "SecurityGuard", 4, _ "RogueKonoko", 5, _ "Switzerland (is melee-immune)", 6, _ "SyndicateAccessory", 7 ) oPPGLayout.AddEnumControl "Team", aListTeams, "", siControlRadio
Spacer
' AddSpacer( [Width], [Height] ) oPPGLayout.AddSpacer 25