Settings

Autocomplete

Engine type

[▓░░] EXACT : start equal.
[▓▓░] FUZZY : this the word. (default)
[▓▓▓] AKIN : similar words.

Order

[▓░░] OFF : none, disable.
[▓▓░] SIMPLE : this the word.
[▓▓▓] SIMILAR : similar words. (default).
The most demanding options have cache memory, so the calculation of searching for something is performed once.

Documentation

- This IDE downloads files and stores them in the LocalStorage for faster uploads.
IDE does not respond:
clear the database to redownload it or refresh the page.
IDE supports & features:
- Autocomplete.
- File manager.
- Syntax Highlighter.
- Preview of errors.
- Compiles for Android and PC.
- Connection with Library::SannyBuilder and data::CrossPlataform

Syntax for conditions

Primitive

This is the most primitive way for the compiler to interpret code.
IF 0
  condition
ELSE_GOTO @Label_false
  body_is_true
GOTO @End
:Label_false
  body_is_false
:End
The entire read stream moves through the conditions and jump points(labels).

Sugared

The IDE has syntactic sugar to prevent us from getting too dizzy, although for now there are very few of these. You can nest them inside each other without any problem.
IF
  condition
THEN
  body
END

IF
  condition
THEN
  is_true
ELSE
  is_false
END
You can also apply several conditions. You only have to indicate if you want to do an AND or OR check. You have a maximum of 8 conditions
IF (AND|OR)
  condition_1
  condition_2
  condition_n+1
THEN
  body
END

Ternary

The syntax comes from JS and since commands can only be typed 1 per line, the IDE allows you to allow the false ternary.
a_contition ? is_true

a_condition ? is_true : is_false
Can also be used to assign a value to a variable
var = a_condition ? is_true : is_false
For now only one condition, but support for more will be coming soon.
Syntax for loops You can work with labels.
:Loop
  body
GOTO @Loop
Or use automated processes.
WHILE condition
  body
END

REPEAT
body
UNTIL condition

FOR var = start <TO|TODOWN> final [STEP (int|float)]
  body
END

FOREACH var_array
  body
END
loop controls are also here
BREAK CONTINUE

FOR 0@ = 0 TO 10
  IF 0@ > 3
  THEN CONTINUE // jump a loop
  END
  IF 0@ > 7
  THEN BREAK // exit of loop
  END
END
There is only one difference. The `WHILE FALSE` loops are not ignored by the compiler, and are compiled as a separate area of the main flow. Their contents are only accessed if you have jumps into their body.
0@ = 0
WHILE FALSE
  :Suma
    0@++
  return
END
printf "0@ = %i" 1s 0@ // 0
gosub @suma
wait 1s
printf "0@ = %i" 1s 0@ // 1
If you make blocks that are too big and you get lost among many `END`, you can use these fasteners:
ENDIF ENDWHILE ENDFOR
All of these are interpreted as the same `END`, so you can use them as worshippers or visual highlighters.
Jumps and Returns Here I will only explain that there are different ways to use a particular opcode, in simpler ways.
for example, to make simple jumps we can do this:
0001: @label // opcode
goto @label // keyword
jump @label // sugar
@label // equivalent
All variants do the same thing and the last one is useful for shorter indications, as in this case:
if 0@ != 1
then @editActor
else @createActor
end

// or

!0@ ? @editActor : @createActor
there is also a special syntax for subroutines(0050) and functions(0AB1).
0050: gosub @label // opcode
gosub @label // keyword
label() // equivalent
the opcode to be used varies depending on whether we pass parameters or expect a return.
0AB1: cleo_call @label input 1 params 0@

0@ = label()   // funcion
0@ = label(1@) // funcion
label(0@)      // function
label()        // subrutine
Opcodes and Keywords

Opcodes

if you explore opcodes in documentations and forums, you don't need to memorize the 4 characters of the opcode or just copy it.
0: nop          -->  0000: nop
FE: actor[...]  -->  00FE: actor[...]
!7F: car[...]   -->  807F: car[...]
1234: wxyz      -->  1234: wxyz

Keywords

This is another way to write opcodes, you just write its name and then it is replaced by the opcode.
nop           -->  0000: nop
WAIT 0        -->  0001: wait 0 ms
not xyz 0@    -->  8ABC: !xyz 0@[...]
These can be written in lowercase or uppercase, and can be negated or contradicted by placing at the beginning of the line one of these 2 executors `!, NOT`.

The IDE also detects if a keyword was written from right to left and corrects it so that it is compileable.
0@ = get_current_time
// is equivalent to
get_current_time = 0@
Classes and Flows

Classes

The IDE is connected to 2 databases to be able to script with legacy or enchanted commands. So if we use aaa.bbb() and ccc.ddd() they will use the same opcode.
Normal:
CLASS.MEMBER(PARAM, VAR)

Method:
CLASS.MEMBER

Conditional:
CLASS.MEMBER(PARAM) == VAR

Setter:
CLASS.MEMBER(PARAM) = VAR

Getter:
VAR = CLASS.MEMBER(PARAM)
The compiler does not know the order of the custom parameters, but instead interprets the orders, depending on how the classes are used.

Everything that is located before the class is relocated at the end of the class.
Multi-Geting:
VAR1 VAR2 = CLASS.MEMBER(PARAM)
VAR1, VAR2 = CLASS.MEMBER(PARAM)
You also do not need to use commas(,) to separate the data. The compiler can detect the change of the data type, using the spaces.

The compiler remembers which was the last class used, so if you use a dot (.) at the beginning of the line, you will access the member of that class.
Last-Used:
.MEMBER(PARAM)

Flows

Keywords that define the workflow and how it should behave on different occasions.
IF, THEN, ELSE, END, WHILE, REPEAT,
UNTIL, FOR, TRUE, FALSE, UNDEFINED,
BREAK, CONTINUE, FOREACH, NOT, NULL
Avoid naming things with these words, the order of how the text preprocessor is executed may break the script.
Constants and Enumerations These are just a nice way to read our code better, so we don't have so many numbers or confusing statements in our code. They are like keywords or classes, which only represent a value and cannot be modified.
// constants
TRUE = 1
_Player = $PLAYER_ACTOR
PI = 3.14159265

// enumerations
PEDTYPE.CIVMALE = 4
KEYCODE.R = 82
BODYPART.TORSO = 1
Directives Directives allow you to configure the compiler for various things. Within Sanny builder, to specify how each opcode should be compiled, prevent the current script from compiling without leaving the source code, import files as extensions of the same, and other things that are not very important. In EIDE there is only one direct
{$I ‹source›}
or
{$INCLUDE ‹source›}
It is used to import files into the one we have open. The compiler replaces the text and copies the content of the file that we pass as a parameter and pastes it in the place where we invoke it.
Comments Comments are lines or sections of code that are removed when compiling the code. They help us leave messages and information about where we are, what something does.Comments are lines or sections of code that are removed when compiling the code. They help us leave messages and information about where we are, what something does and also to decorate.
// Only this line will be commented

/* All the text in here will
disappear in the compiled file */
Decimals The compiler not only has a translator for Hexadecimal and Binary numbers. It can also look up the numerical IDs of the model names.
DEC  -6272_48 -2936 -42 0 5 972 729_0_03
HEX  -0X7FFFFF -0x8AFF 0x0 0x03 0X700000
BIN  -0B011110 -0b1110 0b0 0b01 0B10000000000
OCT  -0O7143 -0o1472 0o0 0o107 0O70523
TIME -2h -2m 1s 3.33S 10M 1H 60fps 30FPS
NAME -#JESTER #fam1 #FAM2 #mini_gun
NOTE -12E5 -3e2 1e9 10e+2 16E-3
there is also a syntax for filling color fields in this way.
c#123        =>   11 22 33
c#123f       =>   11 22 33 FF
c#131377     =>   13 13 77
c#131377CC   =>   13 13 77 CC
Useful for when we smell colors from the Internet and, of course, well interpreted.
draw_box 1f 1f 2f 2f c#2323ABFF
// traslated to
draw_box 1.0 1.0 2.0 2.0 35 35 171 255
Floaters If you program in any language, you may be used to some of its syntax. Here you will be able to use it.
CSS -.0025 -.97 .0 .42 .736
JS  -2_823.2 0.6_608 48_386.93
PY  -42.8362 -3.5 1.0 142.8638
C#  -20F -13.7f 1f 27f 52.86F
R   -1.2E7 5.1e8 7.1e+2 9.3E-2
You can begin or end a number with a period (.) or end it with `f`. Scientific notation (e) and separators (_) are also available.
Literals The editor supports the classic LONG and SHORT formats of SB, and the JS BACKSTICK.
SHORT  'Abc'    09,41-62-63-00-00-00-00-00
LONG   "Abc"    0E,03,41-62-63
BACKS  `"Abc"`  0E,05,22-41-62-63-22
Character escapes can also be made with the slash (\t, \n, \", \xff).
Variables We do not need to declare variable types, or at least in most cases.
0@ = 123 // INT
0@ = 1.3 // FLOAT
0@ = '2' // SHORT
0@ = "2" // LONG
0@ = `2` // LONG
You can define the type of a variable with a prefix or subfix; I, F, S and V.
ID TARGET USE
I INT 2@i i$2
F FLOAT 2@f f$2
S SHORT STRING 2@s s$2
V LONG STRING 2@v v$2
This to perform precise operations.
:sumFloat
  0@ += 1@
ret 1 0@ // return INT : ❌
In this case, this function is expected to do a FLOAT operation, but since they are not defined, they will do an INT operation. this can be fixed, if we define the type of one.
:sumFloat
  0@f += 1@
ret 1 0@ // return FLOAT : 👍
The IDE remembers the last variable definitions and remembers if they went from INT to FLOAT and the other way around.

Locals with names

In every language there can be good and bad practices. And here things can be considered a hate crime, because of how dangerous some actions can be.
int $var = 0 // ⚠️ Warning
int var = 0 // 👍 Perfect
The way to declare these variables is simple: Syntax
‹type› ‹name_var› [= ‹value›]
  • type: any type of non-array variable [int|float|short|long|string]
  • name_var: Any name composed of letters, numbers, or underscores. (but they cannot begin with numbers)
  • value: optional, the initial value. defaults are 0, 0.0, '' or ""
Examples
int index
float accuracy= 100.0
short gxt = 'CHEAT0'
long anim = "IDLE_SEAT"
string foo = `banana`
You can always change the data type of each variable, as long as that intention is expressed like this:
int variable
float variable

varible // is float
It is important to know that these variables have a scope limit.
Objects This is a type of variable data, which is used to store a collection of data, giving each property its own attributes. Syntax
object ‹name› = {
  ‹type› ‹name› [ = ‹value›],
  ‹type› ‹name› [ = ‹value›],
  ...
}
  • name: The name of the object variable.
  • type: type of data that stores a property.
  • value: optional, any value. defaults to 0 or empty strings.
Examples
// initialization
object Camera = {
  int flags,
  float speed = 1.5
}

// re assigned
Camera.flags = 28

// in constant
const SPEED = Camera.speed
SPEED = 2.0
This multiplies its potential use as an array with these data structures. But you can't put arrays into objects.
Arrays Everyone already knows the syntax for writing an ARRAY in Sanny Builder, and if you don't, I'll show it here with an example.
var_main(var_index,size_and_type)

example: 0@(1@,20i)
And we can use it anywhere as a common variable.

Sanny, is extremely strict with syntaxes and does not support writing spaces in them, so if you make any assignment or anything, you must write it like this
0@(1@,20i) = 123
Enchanti offers a little more flexibility here. It does not require you to set the type of the data collection, (INT, FLOAT, SHORT, LONG) nor does it require you to set the size of the collection.
0@(1@)          = '2'
0@(1@,20)       = "2"
0@(1@, 20)      = `2`
0@f(1@,20)      = 1.3
0@(1@,20i)      = 123
0@(1@,20)f      = 1.3
float 0@(1@,20) = 1.3
If you don't specify the type, the IDE will try to know what data you want to store. Be careful though, it only works for assigning constant data for the moment.
If you do not specify the size, the IDE will set the number to 20, by default.
Constants are not left out. They are also supported and you can set their type as you see fit.
a(b)          = '2'
a(b,20)       = "2"
a(b, 20)      = `2`
a(b,20)f      = 1.3
a(b,20i)      = 123
float a(b,20) = 1.3

Enhanti

The most beautiful way to code. Syntax definition
‹type› ‹name_var›[length] [= ‹values›]
  • type: the only type of data that the array stores.
  • name_var: any variable name.
  • length: optional, the length of the array. if not defined, the number of elements in `values` will be taken
  • values: optional, all values are blank.
Syntax manipulation
‹name_var›‹index›
  • name_var: any defined array variable.
  • index: any variable or number from 0 to the maximum of the array.
Examples
// method 1
int Integers = [true, false]

// method 2
float Floaters[5]
Floaters[2] = 32

// method 3
string Texts[2] = ["hello", "world"]

// method 4
int index = 1
Texts[index] = "mati"
Declarations and assignments are similar to real programming languages. The length number starts at 0, and the location at 1, and the length cannot be 0 or it will be invalid.

Matrixes

There is also support for 2D arrays and the same syntaxes are shared.
int Matrix[3][3] = [[1,2,3],[4,5,6],[7,8,9]]

i = 2
Matrix[i][2] = 5

Objets

It is not possible to make a 2d array at the same time as an array of objects. But at least you can make an array of Objects.

Instead of using the `object` keyword we will use `class` to define the structure of our array and we will not pass any value to it:
class IEntity = {
  int type,
  int flags
}
and now we just write the object as if it were a data type and we don't pass any values to it either:
IEntity entities[10]
With this we already have a collection of objects and we can easily access each one, writing it in these ways
// method 1
entities[3].type = PEDTYPE.CIVMALE

// method 2
const Pedro = entities[2]
Pedro.flags = 0b1110

// method 3
index = 1
actores[index].type = PEDTYPE.GANG1
Hexadecimals The IDE works with the same syntax as SB, with some limitations. You cannot insert variables yet, but you can use the hex multiplication operators :)
HEX
 0 00 0(2)   --->  00 00 00 00
 "hello"     --->  68 65 6C 6C 6F
 `hello`     --->  68 65 6C 6C 6F
 'hello'     --->  68 65 6C 6C 6F 00
END
The multiplication function, accepts arithmetic operations and rounds them to the nearest number.
hex
 0(4)   --->  00 00 00 00
 0(4*2) --->  00 00 00 00 00 00 00 00
 0(4.6) --->  00 00 00 00 00
 0(4.3) --->  00 00 00 00
end
Operatives

Sanny

You have all the SB expressions and one extra.
0@++         -->  000A: 0@ += 1
0@ <> 1@     -->  803A: 0@ != 1@
0@ = 1@      -->  0085: 0@ = 1@
0@ = 1@ + 2@ -->  0A8E: 0@ = 1@ + 2@ // int
0@f = 1@ + 2@-->  XXXX: 0@ = 1@ + 2@ // float
0@ =# 1@     -->  0092: 0@ = int_to_float 1@
0@ =& 1@     -->  0AC7: 0@ = var 1@ pointer
0@ +=@ 1@    -->  007B: 0@ += delta_time * 1@
0@ &= 1@     -->  0B17: 0@ &= bit 1@
the compiler remembers the data type of each manually assigned variable, so you don't have to worry about the opcode used.

you can also force a change of operation, adding a subfix (I or F) in the variable
0@f++        -->  XXXX: 0@ += 1.0
0@f <> 1@    -->  XXXX: 0@ != 1@
0@ = 1@f     -->  XXXX: 0@ = 1@
0@ =# 1@f    -->  XXXX: 0@ = float_to_int 1@
float 0@ = 1@-->  XXXX: 0@f = 1@

Enchanti

if only one variable is written in a line, it is passed as a condition.
0@           -->  0039: 0@ == true
!0@          -->  0039: 0@ == false
if you write any operation backwards, the IDE will try to put the operation in the correct order.
1 = 0@       -->  0@ = 1
1 == 0@      -->  0@ == 1
1 += 0@      -->  0@ += 1
You can also assign a negated value to the variables, or see is truthy.
0@ = !1@     -->  1@ == 1 ? 0@ = 0 : 0@ = 1
0@ = !!1@    -->  1@ == 0 ? 0@ = 1 : 0@ = 0
0@ = 1@t     -->  1@ != 0 ? 0@ = 1 : 0@ = 0
Or why not, your own condition? ;)
0@ = 1@ == 2@
// is equivalent to
0@ = 1@ == 2@ ? true : false
Fixed and temporary assignment operators are also available anywhere in the code.
Car.Exist(0@(++1@,10i))
// is compiled before the line
1@ += 1
Car.Exist(0@(1@,10i))

---

Actor.Angle = 1@f++
// is compiled after the line
Actor.Angle = 1@
1@ += 1.0

---

wait 1@+30fps
// is compiled before and after the line
1@ += 30fps
wait 1@
1@ -= 30fps
This syntax only discriminates spaces and commas.

And cascading operations can also be performed in this manner
1@ = 3 * 5 + 6
// is compiled at cascade in the line
1@ = 3
1@ *= 5
1@ += 6
Parameters The IDE can identify when an opcode has extra or missing parameters.
nop  // ok     ->  00 00
wait // error  ->  missing params
wait 0 // ok   ->  01 00 04 00
whenever extra parameters are entered in opcodes that do not allow them, the latter will be removed.
wait 0 33 22   ->  wait 0
Of course, this does not affect opcodes with undefined number of parameters.
cleo_call @func params 1 enter 0x0A
But let's imagine that an opcode is not found in the IDE database.
In this case, the IDE will auto-assign the number of parameters to a fixed one and depending on the number of parameters it used the first time it was invoked.
XXXX: gg 3@
// ok
// OP:XXXX = 1 param

XXXX: gg 24@ 33
// error
// OP:XXXX has 1 param, not 2.
It can adapt its parameter limiter according to your needs, so you can write a single script for Android and PC.
WRITE_MEMORY 1 2 3
// missing (1||2) parameters
WRITE_MEMORY 1 2 3 4
// ok, for PC
WRITE_MEMORY 1 2 3 4 5
// ok, for Android
WRITE_MEMORY 1 2 3 4 5 6
// is cleaner and ok
LOAD_ALL_STREAMING_MODELS
// is mobile and occupy the same opcode
Command finder with IA Let's be honest, there is no AI like Copilot here, but a simple scoring algorithm, which searches for the title or description closest to our request.
Syntax
// ‹message› (??|??)
This is a built-in tool in the editor. So to use it, you just have to position yourself on a line that has no written content, and proceed to make a comment.

Here you just describe what you need (in English) and when you finish, end the line with '??' to ask for an opcode and it will appear with the commented parameters. Example
// create a actor??
Result
// create a actor
CREATE_CHAR {PedType} {model_char} {float} {float} {float} = {var_any}
//Creates a character at the specified location, with the specified model and pedtype
or '!!' to auto-complete them with usage examples.
Example
// create a actor!!
Result
CREATE_CHAR PEDTYPE.CIVMALE [model_char] 23.56 21.87 44.94 = $I0J

The IDE limits some features for better performance.
- The syntax highlighter only colors the lines near the cursor.
- Autocomplete is limited to displaying a maximum of 400 results.
- Autocomplete is only rendered if 0.2 seconds have passed since the last keystroke.
Enchanti IDE
⥅