sannybuilder / dev

Sanny Builder Bug Tracker and Roadmap development
https://sannybuilder.com
49 stars 0 forks source link

Add `Range(var, min, max)` to Built-in Commands #206

Open MatiDragon-YT opened 2 years ago

MatiDragon-YT commented 2 years ago

The idea and function of this command would be to limit the value of a variable, keeping it within a specified range. Looking to reduce 6 lines of code to a single line.

Range(0@, 1, 6) // int or float
/** Parameters:
 * 1 - var or lvar
 * 2 - min value
 * 3 - max value 
*/

translate to

if 0@ < 1
then 0@ = 1
end
if 0@ > 6
then 0@ = 6
end
wmysterio commented 2 years ago

This procedure is called Clamp.

I like the idea of adding internal functions to SB like INC or others. But this could potentially conflict or duplicate opcodes that could implement the same action.

MatiDragon-YT commented 2 years ago

Glad to hear your opinion @wmysterio.

There is a library (.cleo) that adds these 2 opcodes for GTA SA:

0EF4: clamp_float 1@ min 2@ max 3@ store_to 4@
0EF7: clamp_int 1@ min 2@ max 3@ store_to 4@

But not for other games. And it would be nice to have this as an alternative for everyone. Plus I don't think it would be too hard to add it as a function that is translated internally, in a pre-processing before compilation (binary translation).

In most modern languages, this is quite easy to implement. In JS just using the remplace() function with a RegExp is enough. However, I don't know the world of the Rust language (the one used by SannyBulder). I don't know if that would be enough to make a "parse"..

@x87 what do you think about it? After all, you are the author of this beautiful IDE.

Pss: the name of the function does not matter. Let's talk about the feature only

x87 commented 2 years ago

I like the general idea of macros defined in the code. For example:

macro Range(i,min,max)

if i < min
then i = min
end
if i > max
then i = max
end

end

so then you can use Range(0@, 1, 6) and the compiler unwraps the macro into the given code.

wmysterio commented 2 years ago

I like the general idea of macros defined in the code

Hmmm, is it then possible to dynamically add a macro as a class member (pseudo class member)?

macro Actor.CreateWithHeading( handle, type, model, x, y, z, heading )
    handle = Actor.Create( type, model, x, y, z )
    Actor( handle ).Angle = heading
end

// ...

Actor.CreateWithHeading( 0@, 4, #WMYDRUG, 0.0, 0.0, 0.0, 180.0 )
MatiDragon-YT commented 2 years ago

Ohh that would be very good, it would also serve to make multiplatform mods faster. In cases where the opcode changes but the function does not.

macro Cleo.SetVar(direction, value)
    if $CompileMode == eFOR_PC
    then 0AAA: set_cleo_shared_var direction value
    else 0BBB: set_cleo_shared_var direction value
    end
end

[...]

Cleo.SetVar(GAME_SPEED, 1.0)
wmysterio commented 2 years ago

Ohh that would be very good, it would also serve to make multiplatform mods faster. In cases where the opcode changes but the function does not.

Hmm, I think that directives would be more suitable for multi-platform code:

macro Cleo.SetVar(direction, value)
    {$if eFOR_PC } // modeSA, modeVC, modeSA_PC, cleo4.0 ...
    0AAA: set_cleo_shared_var direction value
    {$else}
    0BBB: set_cleo_shared_var direction value
    {$end}
end

The compiler needs to know that an opcode exists in order to attempt to compile it or throw an error.