FOnline Development > Questions and Answers

Calling a script from AngelScript

(1/2) > >>

wladimiiir:
Let's say, I have string with the value of "myCoolModule@mySuperCoolFunction". Is there a way how to call the script function that is represented by this value?
I could not find any useful info that this could be done from AngelScript. The only way, which comes to my mind, is to call DLL with C++ function which would call the AngelScript function in return.

Any ideas? Thanks.

Wipe:
Not counting .dlls... hmm, let the workarounds flow~

Server-side you can use time events to run function, with zero delay. Of course, you can't get return value of the function then, plus you'll be limited to int[], uint[], and everything what can be bytepacked as arguments.
Client-side you can use RunServerScriptUnsafe() and pass your string - server's job is to call RunClientScript() using your string as function argument. Same limitations as above.

;D

wladimiiir:
Yeah, I am aware of those options. :)

What I am trying to do is to call fix_ functions in fix_boy.fos, basically, as I am remaking the FixBoy on client side, calling my unsafe_fix functions on server side, which should try to call script functions defined in CraftItem.

So none of this can be used, because they use different arguments. :(

Ghosthack:
Sounds like you have to do a call to a wrapper function with a string argument which can then call the appropriate function, you're able to reduce the amount of boilerplate code by using macros for definitions and calls.

Wipe:
Got bored with own bugs, so why not create some for others :D


--- Code: ---#define valid#(ptr) (@ptr!= null)

funcdef int fixFunc( Critter@ player, int state, CraftItem& craft );

class FixData
{
    string Name;
    private fixFunc@ func;

    FixData( string& name, fixFunc@ func )
    {
        this.Name = name;
        @this.func = func;
    }

    int Call( Critter@ player, int state, CraftItem& craft )
    {
        if( valid(func) )
            return( func( player, state, craft ));

        return( -1 ); // error mark
    }
};

array<FixData> Wrapper;

void InitFixboy()
{
    Wrapper.insertLast( FixData( "fix_silly", @fix_silly ));
    Wrapper.insertLast( FixData( "fix_dummy", @fix_dummy ));
}

int fix_silly( Critter@ player, int state, CraftItem& craft )
{
    return( 1207 );
}

int fix_dummy( Critter@ player, int state, CraftItem& craft )
{
    return( 1337 );
}

void unsafe_fix( Critter@ player, int craftItem, int state, int, string@ func, array<int>@ )
{
    int result = -1; // error mark

    if( valid(func) && func.length() > 0 )
    {
        for( uint w=0, wLen=Wrapper.length; w<wLen; w++ )
        {
            if( Wrapper[w].Name == func )
            {
                CraftItem@ craft = GetCraftItem( craftItem );
                if( valid(craft) )
                    result = Wrapper[w].Call( player, state, craft );

                break;
            }
        }
    }

    Log( "RESULT "+(valid(func)?func:"<invalid>")+":"+result );

    if( result == -1 )
    {
         // error handling
         return;
    }

    // further result processing
}

#ifdef __ASCOMPILER
void test()
{
    InitFixboy();

    unsafe_fix( null, 0, 0, 0, "fix_silly", null );
    unsafe_fix( null, 0, 0, 0, "fix_dummy", null );
    unsafe_fix( null, 0, 0, 0, "fix_incorrect", null );
    unsafe_fix( null, 0, 0, 0, null, null );
}
#endif

--- End code ---

So yeah, pure AS example; hope it's clear enough for you.

All manual work left is to fill InitFixboy() with all of yours fix_ functions; sadly can't see a way to automate it. I also used Critter@ instead of Critter& for test purposes, so that one need fixing too. Can still be improved, for example by scrapping string@ func usage and relay on CraftItem::Script instead - again, it's done that way or ASCompiler would get mad.

As i understand you want to avoid .dlls [where whole thing would be much easier and shorter] for maximum portability, or is there any other reason?

Navigation

[0] Message Index

[#] Next page

Go to full version