Lev_Landau Posted March 7, 2014 Share Posted March 7, 2014 (edited) - Edited April 24, 2014 by Lev_Landau Link to comment Share on other sites More sharing options...
Link2012 Posted March 7, 2014 Share Posted March 7, 2014 (edited) You'll need to do that in somewhat a manual way.First, you'll need a point of reference to how many extra parameters you'll have, in the case of those opcodes you have the "number of params" and the "number of formating".Then you'll just need to collect the number of parameters needed using the respective SDK functions (CLEO_GetFloatOpcodeParam, CLEO_GetIntOpcodeParam, etc etc).Now, how do you know what parameter type it is, a string, int, float...? Use CLEO_GetOperandType and check the result. The SDK should have a enum with the operand types but if it doesn't you can look here on the datatypes table.Now, what if you don't have a number of parameters to collect but you still want to collect all extra parameters, just like 004F? Simple, the last operand type will be 0x0, it singalizes the end of the extra parameters list.So, here we go with a example: /* bla */ opcode_7FFF(/* bla bla bla */){ int operand; // bla bla bla while(operand = CLEO_GetOperandType(thread)) // While not the end of the extra parameters { switch(operand) { // Check out the operand type and do your stuff // Put your cases here <> } }} Edited March 7, 2014 by LINK/2012 Link to comment Share on other sites More sharing options...
Lev_Landau Posted March 7, 2014 Author Share Posted March 7, 2014 (edited) - Edited April 24, 2014 by Lev_Landau Link to comment Share on other sites More sharing options...
Link2012 Posted March 8, 2014 Share Posted March 8, 2014 (edited) Most trivial options: Option 1: Let the 'Log' function handle the parameters collection Option 2: Store the parameters + parameter type on an array and send to the logging func. I guess the option 1 is better, option 2 looks dirty. Edited March 8, 2014 by LINK/2012 Link to comment Share on other sites More sharing options...
Lev_Landau Posted March 8, 2014 Author Share Posted March 8, 2014 (edited) - Edited April 24, 2014 by Lev_Landau Link to comment Share on other sites More sharing options...
Link2012 Posted March 8, 2014 Share Posted March 8, 2014 (edited) You could take the array parameter flags, check out here But really, I don't think you should, the game itself don't care about what you're sending, it expects you to be sending what it wants. For example, 0001 (WAIT), the game expects a integer, right? What if you send a float (e.g. WAIT 1.0)? Well, what will happen is that it will still collect a integer and then will WAIT 0x3F800000 (0x3F800000 is the binary representation of the floating point 1.0) So really, just parse your formats, if you come up with an '%f' tell CLEO to collect a float, with a '%s', collect a string, and so on. Here's a simple example: void Log(const char* format, CScriptThread* thread){ for(; *format; ++format) { if(*format == '%') { if(format[1] == 'f') { // Collect a float and sprintf into your buffer, or print it already, dunno } else if /* and so on */ {} } else { /**/ } }}/**/ opcode_7FFF(/**/){ Log(CollectStringParameter(thread), thread); // Skip unused params if you want, CLEO has a SDK func to skip unused params.} Edited March 8, 2014 by LINK/2012 Link to comment Share on other sites More sharing options...
Lev_Landau Posted March 13, 2014 Author Share Posted March 13, 2014 (edited) - Edited April 24, 2014 by Lev_Landau Link to comment Share on other sites More sharing options...
DK22Pac Posted March 13, 2014 Share Posted March 13, 2014 CLEO SDK can't handle such opcodes. You need to do operations with CScriptThread data manually. Link to comment Share on other sites More sharing options...
Lev_Landau Posted March 13, 2014 Author Share Posted March 13, 2014 (edited) - Edited April 24, 2014 by Lev_Landau Link to comment Share on other sites More sharing options...
Deji Posted March 13, 2014 Share Posted March 13, 2014 CLEO SDK can't handle such opcodes. You need to do operations with CScriptThread data manually. What may handle them? There are native opcodes with variable number of parameters and I also found some custom opcodes, that accept variable number of parameters as well (namely SAMPFUNCS) Simply check: if( *thread->ip != NULL ) before trying to get a parameter. However, the purpose of the 'null data type' is for the end of an argument list - not for the end of "variable number of arguments" - that is strictly a SB reference and it's common to confuse it's simplifications of what was once a more complex language. In the original engine it's never used for anything other than transmitting parameters to another script. CLEO actually never does any different - for most opcodes (CALL and RET) they are being used in pretty much the same way. All other times, the number of arguments and more importantly the types have to be known somehow. Pretty pointless trying to get everything when you know exactly what you need. Anyway, CLEO 4 has already done this and the source code is available anyway, but here's the specific function of interest: https://pastebin.com/1nSRi0zi As you can see, no need for getting a variable number of arguments, but you can call SkipOpcodeParams afterwards if you want to allow something that shouldn't happen. The variant for sscanf-style operations might be of interest, too, but I'll just post it here: int *result = (int *)GetScriptParamPointer(thread); SCRIPT_VAR *ExParams[35]; // read extra params for(int i = 0; i<35; i++) { if(*thread->ip) { ExParams[i] = GetScriptParamPointer(thread); cExParams++; } else ExParams[i] = nullptr; } ++thread->ip; *result = sscanf(src, format, /* extra parameters (will be aligned automatically, but the limit of 35 elements maximum exists) */ ExParams[0], ExParams[1], ExParams[2], ExParams[3], ExParams[4], ExParams[5], ExParams[6], ExParams[7], ExParams[8], ExParams[9], ExParams[10], ExParams[11], ExParams[12], ExParams[13], ExParams[14], ExParams[15], ExParams[16], ExParams[17], ExParams[18], ExParams[19], ExParams[20], ExParams[21], ExParams[22], ExParams[23], ExParams[24], ExParams[25], ExParams[26], ExParams[27], ExParams[28], ExParams[29], ExParams[30], ExParams[31], ExParams[32], ExParams[33], ExParams[34]); Link to comment Share on other sites More sharing options...
Link2012 Posted March 14, 2014 Share Posted March 14, 2014 How you need to do that manually? CLEO_GetOperandType returns the current byte (and thus the datatype) without moving PC. Link to comment Share on other sites More sharing options...
Lev_Landau Posted March 14, 2014 Author Share Posted March 14, 2014 (edited) - Edited April 24, 2014 by Lev_Landau Link to comment Share on other sites More sharing options...
Lev_Landau Posted March 25, 2014 Author Share Posted March 25, 2014 (edited) - Edited April 24, 2014 by Lev_Landau Link to comment Share on other sites More sharing options...
Silent Posted March 25, 2014 Share Posted March 25, 2014 (edited) Opcodes with an undefined amount of parameters 'terminate' the param list with 00, are you handling this in your code? If you don't, it'll next be executed as a part of opcode ID and therefore crash. Edited March 25, 2014 by Silent Link to comment Share on other sites More sharing options...
Lev_Landau Posted March 27, 2014 Author Share Posted March 27, 2014 (edited) - Edited April 24, 2014 by Lev_Landau Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now