// Set a global variable value for a context BOOL eventSetContextVar(SCRIPT_CONTEXT *psContext, UDWORD index, INTERP_VAL *data) { INTERP_VAL *psVal; if (!eventGetContextVal(psContext, index, &psVal)) { return false; } if(!interpCheckEquiv(psVal->type, data->type)) { ASSERT( false, "eventSetContextVar: Variable type mismatch (var type: %d, data type: %d)", psVal->type, data->type); return false; } // Store the data if(data->type == VAL_STRING) { ASSERT(data->v.sval != NULL, "eventSetContextVar: ininitialized source string pointer"); strcpy(psVal->v.sval, data->v.sval); free(data->v.sval); //not needed anymore data->v.sval = NULL; } else { memcpy(psVal, data, sizeof(INTERP_VAL)); } return true; }
// load the context information for the script system static BOOL eventLoadContext(const SDWORD version, char *pBuffer, UDWORD *pSize, BOOL bHashed) { UDWORD size, valSize,stringLen; SDWORD numVars, i, numContext, context; SCRIPT_CONTEXT *psCCont; INTERP_TYPE type; SCR_VAL_LOAD loadFunc; char *pPos; char *pScriptID = NULL; UDWORD hashedName; SCRIPT_CODE *psCode; CONTEXT_RELEASE release; INTERP_VAL *psVal, data; size = 0; pPos = pBuffer; // get the number of contexts in the save file endian_sword((SWORD*)pPos); numContext = *((SWORD *)pPos); pPos += sizeof(SWORD); size += sizeof(SWORD); // go through the contexts for(context=0; context < numContext; context += 1) { if(bHashed) { endian_udword((UDWORD*)pPos); hashedName = *((UDWORD*)pPos); psCode = (SCRIPT_CODE*)resGetDataFromHash("SCRIPT", hashedName); pPos += sizeof(UDWORD); } else { // get the script code pScriptID = (char *)pPos; psCode = (SCRIPT_CODE*)resGetData("SCRIPT", pScriptID); pPos += strlen(pScriptID) + 1; } // check the number of variables endian_sword((SWORD*)pPos); numVars = psCode->numGlobals + psCode->arraySize; if (numVars != *((SWORD*)pPos)) { ASSERT(false, "Context %d of %d: Number of context variables (%d) does not match the script code (%d)", context, numContext, numVars, *((SWORD*)pPos)); return false; } pPos += sizeof(SWORD); release = (CONTEXT_RELEASE)*pPos; pPos += sizeof(UBYTE); // create the context if (!eventNewContext(psCode, release, &psCCont)) { return false; } // bit of a hack this - note the id of the context to link it to the triggers psContList->id = (SWORD)context; if(bHashed) { size += sizeof(UDWORD) + sizeof(SWORD) + sizeof(UBYTE); } else { size += strlen(pScriptID) + 1 + sizeof(SWORD) + sizeof(UBYTE); } // set the context variables for(i=0; i < numVars; i+= 1) { // get the variable type endian_sword((SWORD*)pPos); type = (INTERP_TYPE) *((SWORD*)pPos); pPos += sizeof(SWORD); size += sizeof(SWORD); // get the variable value if (type < VAL_USERTYPESTART) { data.type = type; endian_udword((UDWORD*)pPos); switch (type) { case VAL_BOOL: data.v.bval = *((BOOL*)pPos); pPos += sizeof(BOOL); size += sizeof(BOOL); break; case VAL_FLOAT: data.v.fval = *((float*)pPos); pPos += sizeof(float); size += sizeof(float); break; case VAL_INT: case VAL_TRIGGER: case VAL_EVENT: case VAL_VOID: case VAL_OPCODE: case VAL_PKOPCODE: data.v.ival = *((UDWORD *)pPos); pPos += sizeof(UDWORD); size += sizeof(UDWORD); break; case VAL_STRING: data.v.sval = (char*)malloc(MAXSTRLEN); strcpy(data.v.sval, "\0"); stringLen = *((UDWORD *)pPos); //read string length pPos += sizeof(UDWORD); size += sizeof(UDWORD); //load string if(stringLen > 0) { strlcpy(data.v.sval, (char *)pPos, MIN(stringLen + 1, MAXSTRLEN)); pPos += stringLen; size += stringLen; } break; case VAL_OBJ_GETSET: /* FIXME: saving pointer on disk! */ data.v.pObjGetSet = *((SCRIPT_VARFUNC*)pPos); pPos += sizeof(SCRIPT_VARFUNC); size += sizeof(SCRIPT_VARFUNC); break; case VAL_FUNC_EXTERN: /* FIXME: saving pointer on disk! */ data.v.pFuncExtern = *((SCRIPT_FUNC*)pPos); pPos += sizeof(SCRIPT_FUNC); size += sizeof(SCRIPT_FUNC); break; default: ASSERT( false, "eventLoadContext: invalid internal type" ); } // set the value in the context if (!eventSetContextVar(psCCont, (UDWORD)i, &data)) { debug( LOG_FATAL, "eventLoadContext: couldn't set variable value" ); abort(); return false; } } else { // user defined type loadFunc = asScrTypeTab[type - VAL_USERTYPESTART].loadFunc; ASSERT( loadFunc != NULL, "eventLoadContext: no load function for type %d\n", type ); endian_uword((UWORD*)pPos); valSize = *((UWORD *)pPos); pPos += sizeof(UWORD); size += sizeof(UWORD); // get the value pointer so that the loadFunc can write directly // into the variables data space. if (!eventGetContextVal(psCCont, (UDWORD)i, &psVal)) { debug( LOG_FATAL, "eventLoadContext: couldn't find variable in context" ); abort(); return false; } if (!loadFunc(version, psVal, pPos, valSize)) { debug( LOG_FATAL, "eventLoadContext: couldn't get variable value" ); abort(); return false; } pPos += valSize; size += valSize; } } } *pSize = size; return true; }
// load the context information for the script system static bool eventLoadContext(WzConfig &ini) { SDWORD numVars, numContext; SCRIPT_CONTEXT *psCCont; SCR_VAL_LOAD loadFunc; UDWORD hashedName; SCRIPT_CODE *psCode; CONTEXT_RELEASE release; INTERP_VAL *psVal, data; // get the number of contexts in the save file numContext = ini.value("general/contexts", 0).toInt(); if (numContext == 0) { debug(LOG_FATAL, "No script contexts found -- failed to load script data"); return false; } // go through the contexts for (int context = 0; context < numContext; context++) { ini.beginGroup("context_" + QString::number(context)); hashedName = ini.value("context").toUInt(); numVars = ini.value("numVars").toInt(); release = (CONTEXT_RELEASE)ini.value("release").toInt(); psCode = (SCRIPT_CODE*)resGetDataFromHash("SCRIPT", hashedName); // create the context if (!eventNewContext(psCode, release, &psCCont)) { debug(LOG_FATAL, "Failed to create new context"); return false; } if (numVars != psCode->numGlobals + psCode->arraySize) { ASSERT(false, "Context %d of %d: Number of context variables (%d) does not match the script code (%d)", context, numContext, numVars, psCode->numGlobals + psCode->arraySize); return false; } // bit of a hack this - note the id of the context to link it to the triggers psContList->id = context; ini.beginGroup("var"); // set the context variables for (int i = 0; i < numVars; i++) { ini.beginGroup(QString::number(i)); // get the variable type INTERP_TYPE type = (INTERP_TYPE)ini.value("type").toInt(); // get the variable value if (type < VAL_USERTYPESTART) { data.type = type; switch (type) { case VAL_BOOL: data.v.bval = ini.value("data").toBool(); break; case VAL_FLOAT: data.v.fval = ini.value("data").toFloat(); break; case VAL_INT: case VAL_TRIGGER: case VAL_EVENT: case VAL_VOID: case VAL_OPCODE: case VAL_PKOPCODE: data.v.ival = ini.value("data").toInt(); break; case VAL_STRING: data.v.sval = (char*)malloc(MAXSTRLEN); strcpy(data.v.sval, ini.value("var/" + QString::number(i) + "/data").toString().toAscii().constData()); break; case VAL_OBJ_GETSET: case VAL_FUNC_EXTERN: // do nothing break; default: ASSERT(false, "Invalid internal type"); } // set the value in the context if (!eventSetContextVar(psCCont, i, &data)) { debug(LOG_FATAL, "Could not set variable value"); return false; } } else { // user defined type loadFunc = asScrTypeTab[type - VAL_USERTYPESTART].loadFunc; ASSERT(loadFunc, "No load function for type %d", type); // get the value pointer so that the loadFunc can write directly // into the variables data space. if (!eventGetContextVal(psCCont, i, &psVal)) { debug(LOG_FATAL, "Could not find variable %d in context %d", i, context); return false; } if (!loadFunc(psVal, ini)) { debug(LOG_FATAL, "Could not get variable value context %d, variable %d", context, i); return false; } } ini.endGroup(); } ini.endGroup(); ini.endGroup(); } return true; }