// load a list of triggers static BOOL eventLoadTriggerList(WZ_DECL_UNUSED const SDWORD version, char *pBuffer, UDWORD *pSize) { UDWORD size, event, offset, time; char *pPos; SDWORD numTriggers, context, type, trigger, i; SCRIPT_CONTEXT *psContext; size = 0; pPos = pBuffer; // get the number of triggers endian_sdword((SDWORD*)pPos); numTriggers = *((SDWORD*)pPos); pPos += sizeof(SDWORD); size += sizeof(SDWORD); for(i=0; i<numTriggers; i+= 1) { endian_udword((UDWORD*)pPos); time = *((UDWORD*)pPos); pPos += sizeof(UDWORD); endian_sword((SWORD*)pPos); context = *((SWORD*)pPos); pPos += sizeof(SWORD); if (!eventFindContext(context, &psContext)) { debug( LOG_FATAL, "eventLoadTriggerList: couldn't find context" ); abort(); return false; } endian_sword((SWORD*)pPos); type = *((SWORD*)pPos); pPos += sizeof(SWORD); endian_sword((SWORD*)pPos); trigger = *((SWORD*)pPos); pPos += sizeof(SWORD); endian_uword((UWORD*)pPos); event = *((UWORD*)pPos); pPos += sizeof(UWORD); endian_uword((UWORD*)pPos); offset = *((UWORD*)pPos); pPos += sizeof(UWORD); size += sizeof(UDWORD) + sizeof(SWORD)*3 + sizeof(UWORD)*2; if (!eventLoadTrigger(time, psContext, type, trigger, event, offset)) { return false; } } *pSize = size; return true; }
// save the context information for the script system static BOOL eventSaveContext(char *pBuffer, UDWORD *pSize) { UDWORD size, valSize; SDWORD numVars, i, numContext; SCRIPT_CONTEXT *psCCont; VAL_CHUNK *psCVals; INTERP_VAL *psVal; SCR_VAL_SAVE saveFunc; char *pPos; //not hashed char *pScriptID; UDWORD hashedName; UWORD *pValSize = NULL; size = 0; numContext = 0; pPos = pBuffer; // reserve space to store how many contexts are saved if (pBuffer != NULL) { pPos += sizeof(SWORD); } size += sizeof(SWORD); // go through the context list for(psCCont = psContList; psCCont != NULL; psCCont = psCCont->psNext) { numContext += 1; // save the context info //nothashed if (!resGetIDfromData("SCRIPT", psCCont->psCode, &hashedName)) if (!resGetHashfromData("SCRIPT", psCCont->psCode, &hashedName)) { debug( LOG_FATAL, "eventSaveContext: couldn't find script resource id" ); abort(); return false; } numVars = psCCont->psCode->numGlobals + psCCont->psCode->arraySize; if (pBuffer != NULL) { //not hashed strcpy(pPos, pScriptID); //not hashed pPos += strlen(pScriptID) + 1; *((UDWORD*)pPos) = (UDWORD)hashedName; endian_udword((UDWORD*)pPos); pPos += sizeof(UDWORD); *((SWORD*)pPos) = (SWORD)numVars; endian_sword((SWORD*)pPos); pPos += sizeof(SWORD); *pPos = (UBYTE)psCCont->release; pPos += sizeof(UBYTE); } //not hashed size += strlen(pScriptID) + 1 + sizeof(SWORD) + sizeof(UBYTE); size += sizeof(UDWORD) + sizeof(SWORD) + sizeof(UBYTE); // save the context variables for(psCVals = psCCont->psGlobals; psCVals != NULL; psCVals = psCVals->psNext) { for(i=0; i < CONTEXT_VALS; i+= 1) { psVal = psCVals->asVals + i; // store the variable type if (pBuffer != NULL) { ASSERT( psVal->type < SWORD_MAX, "eventSaveContext: variable type number too big" ); *((SWORD*)pPos) = (SWORD)psVal->type; endian_sword((SWORD*)pPos); pPos += sizeof(SWORD); } size += sizeof(SWORD); // store the variable value if (psVal->type == VAL_STRING) { UDWORD stringLen = 0; if(psVal->v.sval != NULL && strlen(psVal->v.sval) > 0) { stringLen = strlen(psVal->v.sval) + 1; } if (pBuffer != NULL) { *((UDWORD *)pPos) = stringLen; endian_udword((UDWORD *)pPos); pPos += sizeof(UDWORD); if(stringLen > 0) { strcpy((char *)pPos, psVal->v.sval); } pPos += stringLen; } size += sizeof(UDWORD) + stringLen; } else if (psVal->type < VAL_USERTYPESTART) { // internal type if (pBuffer != NULL) { /* FIXME: this does not work for VAL_OBJ_GETSET, VAL_FUNC_EXTERN */ *((UDWORD *)pPos) = (UDWORD)psVal->v.ival; endian_udword((UDWORD*)pPos); pPos += sizeof(UDWORD); } size += sizeof(UDWORD); } else { // user defined type saveFunc = asScrTypeTab[psVal->type - VAL_USERTYPESTART].saveFunc; ASSERT( saveFunc != NULL, "eventSaveContext: no save function for type %d\n", psVal->type ); // reserve some space to store how many bytes the value uses if (pBuffer != NULL) { pValSize = (UWORD *)pPos; pPos += sizeof(UWORD); } size += sizeof(UWORD); if (!saveFunc(psVal, pPos, &valSize)) { debug( LOG_FATAL, "eventSaveContext: couldn't get variable value size" ); abort(); return false; } if (pBuffer != NULL) { *pValSize = (UWORD)valSize; endian_uword((UWORD*)pValSize); pPos += valSize; } size += valSize; } numVars -=1; if (numVars <= 0) { // done all the variables ASSERT( psCVals->psNext == NULL, "eventSaveContext: number of context variables does not match the script code" ); break; } } } ASSERT( numVars == 0, "eventSaveContext: number of context variables does not match the script code" ); } // actually store how many contexts have been saved if (pBuffer != NULL) { *((SWORD *)pBuffer) = (SWORD)numContext; endian_sword((SWORD*)pBuffer); } *pSize = size; return true; }
// save a list of triggers static BOOL eventSaveTriggerList(ACTIVE_TRIGGER *psList, char *pBuffer, UDWORD *pSize) { ACTIVE_TRIGGER *psCurr; UDWORD size; char *pPos; SDWORD numTriggers, context; size = 0; pPos = pBuffer; // reserve some space for the number of triggers if (pBuffer != NULL) { pPos += sizeof(SDWORD); } size += sizeof(SDWORD); numTriggers = 0; for(psCurr = psList; psCurr != NULL; psCurr = psCurr->psNext) { numTriggers += 1; if (pBuffer != NULL) { *((UDWORD*)pPos) = psCurr->testTime; endian_udword((UDWORD*)pPos); pPos += sizeof(UDWORD); if (!eventGetContextIndex(psCurr->psContext, &context)) { debug( LOG_FATAL, "eventSaveTriggerList: couldn't find context" ); abort(); return false; } *((SWORD*)pPos) = (SWORD)context; endian_sword((SWORD*)pPos); pPos += sizeof(SWORD); *((SWORD*)pPos) = psCurr->type; endian_sword((SWORD*)pPos); pPos += sizeof(SWORD); *((SWORD*)pPos) = psCurr->trigger; endian_sword((SWORD*)pPos); pPos += sizeof(SWORD); *((UWORD*)pPos) = psCurr->event; endian_uword((UWORD*)pPos); pPos += sizeof(UWORD); *((UWORD*)pPos) = psCurr->offset; endian_uword((UWORD*)pPos); pPos += sizeof(UWORD); } size += sizeof(UDWORD) + sizeof(SWORD)*3 + sizeof(UWORD)*2; } if (pBuffer != NULL) { *((SDWORD*)pBuffer) = numTriggers; endian_sdword((SDWORD*)pBuffer); } *pSize = size; 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; }
/// default value load routine bool scrValDefLoad(SDWORD version, INTERP_VAL *psVal, char *pBuffer, UDWORD size) { char *pPos; DROID *psCDroid; SDWORD index, members, savedMembers; UDWORD id; LEVEL_DATASET *psLevel; DROID_GROUP *psGroup = NULL; const char *pName; bool bObjectDefined; switch ((unsigned)psVal->type) // Unsigned cast to suppress compiler warnings due to enum abuse. { case ST_INTMESSAGE: if ((size == 1) && (*pBuffer == 0)) { psVal->v.oval = NULL; } else { psVal->v.oval = (void*)getViewData(pBuffer); if (psVal->v.oval == NULL) { return false; } } break; case ST_BASEOBJECT: case ST_DROID: case ST_STRUCTURE: case ST_FEATURE: id = *((UDWORD *)pBuffer); endian_udword(&id); if (id == UDWORD_MAX) { psVal->v.oval = NULL; } else { psVal->v.oval = (void*)getBaseObjFromId(id); if (!psVal->v.oval) { debug(LOG_ERROR, "Could not find object id %d", id); } } break; case ST_BASESTATS: case ST_COMPONENT: break; case ST_STRUCTURESTAT: index = getStructStatFromName(pBuffer); if (index == -1) { debug( LOG_FATAL, "scrValDefLoad: couldn't find structure stat %s", pBuffer ); abort(); index = 0; } psVal->v.ival = index; break; case ST_FEATURESTAT: index = getFeatureStatFromName(pBuffer); if (index == -1) { debug( LOG_FATAL, "scrValDefLoad: couldn't find feature stat %s", pBuffer ); abort(); index = 0; } psVal->v.ival = index; break; case ST_BODY: index = getCompFromResName(COMP_BODY, pBuffer); if (index == -1) { debug( LOG_FATAL, "scrValDefLoad: couldn't find body component %s", pBuffer ); abort(); index = 0; } psVal->v.ival = index; break; case ST_PROPULSION: index = getCompFromResName(COMP_PROPULSION, pBuffer); if (index == -1) { debug( LOG_FATAL, "scrValDefLoad: couldn't find propulsion component %s", pBuffer ); abort(); index = 0; } psVal->v.ival = index; break; case ST_ECM: index = getCompFromResName(COMP_ECM, pBuffer); if (index == -1) { debug( LOG_FATAL, "scrValDefLoad: couldn't find ECM component %s", pBuffer ); abort(); index = 0; } psVal->v.ival = index; break; case ST_SENSOR: index = getCompFromResName(COMP_SENSOR, pBuffer); if (index == -1) { debug( LOG_FATAL, "scrValDefLoad: couldn't find sensor component %s", pBuffer ); abort(); index = 0; } psVal->v.ival = index; break; case ST_CONSTRUCT: index = getCompFromResName(COMP_CONSTRUCT, pBuffer); if (index == -1) { debug( LOG_FATAL, "scrValDefLoad: couldn't find constructor component %s", pBuffer ); abort(); index = 0; } psVal->v.ival = index; break; case ST_WEAPON: index = getCompFromResName(COMP_WEAPON, pBuffer); if (index == -1) { debug( LOG_FATAL, "scrValDefLoad: couldn't find weapon %s", pBuffer ); abort(); index = 0; } psVal->v.ival = index; break; case ST_REPAIR: index = getCompFromResName(COMP_REPAIRUNIT, pBuffer); if (index == -1) { debug( LOG_FATAL, "scrValDefLoad: couldn't find repair component %s", pBuffer ); abort(); index = 0; } psVal->v.ival = index; break; case ST_BRAIN: index = getCompFromResName(COMP_BRAIN, pBuffer); if (index == -1) { debug( LOG_FATAL, "scrValDefLoad: couldn't find repair brain %s", pBuffer ); abort(); index = 0; } psVal->v.ival = index; break; case ST_TEMPLATE: id = *((UDWORD *)pBuffer); endian_udword(&id); if (id == UDWORD_MAX) { psVal->v.oval = NULL; } else { psVal->v.oval = (void*)IdToTemplate(id, ANYPLAYER); if ((DROID_TEMPLATE*)(psVal->v.oval) == NULL) { debug( LOG_FATAL, "scrValDefLoad: couldn't find template id %d", id ); abort(); } } break; case ST_TEXTSTRING: { const char* str; char* idStr; uint16_t len; if (size < sizeof(len)) { debug(LOG_ERROR, "Data size is too small, %u is expected, but %u is provided", (unsigned int)(sizeof(len)), (unsigned int)size); return false; } len = *((uint16_t*)pBuffer); endian_uword(&len); if (size < sizeof(len) + len) { debug(LOG_ERROR, "Data size is too small, %u is expected, but %u is provided", (unsigned int)(sizeof(len) + len), (unsigned int)size); return false; } if (len == 0) { psVal->v.sval = NULL; return true; } idStr = (char *)malloc(len); if (!idStr) { debug(LOG_ERROR, "Out of memory (tried to allocate %u bytes)", (unsigned int)len); // Don't abort() here, as this might be the result from a bad "len" field in the data return false; } memcpy(idStr, pBuffer + sizeof(len), len); if (idStr[len - 1] != '\0') { debug(LOG_WARNING, "Non-NUL terminated string encountered!"); } idStr[len - 1] = '\0'; str = strresGetString(psStringRes, idStr); if (!str) { debug(LOG_ERROR, "Couldn't find string with id \"%s\"", idStr); free(idStr); return false; } free(idStr); psVal->v.sval = strdup(str); if (!psVal->v.sval) { debug(LOG_FATAL, "Out of memory"); abort(); return false; } } break; case ST_LEVEL: if ((size == 1) && (*pBuffer == 0)) { psVal->v.sval = '\0'; } else { psLevel = levFindDataSet(pBuffer); if (psLevel == NULL) { debug( LOG_FATAL, "scrValDefLoad: couldn't find level dataset %s", pBuffer ); abort(); } psVal->v.sval = psLevel->pName; } break; case ST_RESEARCH: if ((size == 1) && (*pBuffer == 0)) { psVal->v.oval = NULL; } else { psVal->v.oval = (void*)getResearch(pBuffer); if (psVal->v.oval == NULL) { debug( LOG_FATAL, "scrValDefLoad: couldn't find research %s", pBuffer ); abort(); } } break; case ST_GROUP: bObjectDefined = true; if (psVal->v.oval == NULL) { DROID_GROUP *tmp = grpCreate(); tmp->add(NULL); psVal->v.oval = tmp; } pPos = pBuffer; if (version < 2) { members = size / sizeof(UDWORD); } else if (version < 3) { members = (size - sizeof(SDWORD)*4) / sizeof(UDWORD); } else { members = (size - sizeof(SDWORD)*6) / sizeof(UDWORD); // get saved group member count/nullpointer flag endian_sdword((SDWORD*)pPos); bObjectDefined = ( *((SDWORD *)pPos) != UNALLOCATED_OBJECT ); if(bObjectDefined) { savedMembers = *((SDWORD *)pPos); // get number of saved group members ASSERT(savedMembers == members, "scrValDefLoad: calculated and saved group member count did not match." ); } pPos += sizeof(SDWORD); } // make sure group was allocated when it was saved (relevant starting from version 3) if( version < 3 || bObjectDefined ) { if (version >= 2) { // load the retreat data psGroup = (DROID_GROUP*)(psVal->v.oval); endian_sdword((SDWORD*)pPos); psGroup->sRunData.sPos.x = *((SDWORD *)pPos); pPos += sizeof(SDWORD); endian_sdword((SDWORD*)pPos); psGroup->sRunData.sPos.y = *((SDWORD *)pPos); pPos += sizeof(SDWORD); endian_sdword((SDWORD*)pPos); psGroup->sRunData.forceLevel = (UBYTE)(*((SDWORD *)pPos)); pPos += sizeof(SDWORD); endian_sdword((SDWORD*)pPos); psGroup->sRunData.leadership = (UBYTE)(*((SDWORD *)pPos)); pPos += sizeof(SDWORD); } if (version >= 3) { endian_sdword((SDWORD*)pPos); psGroup->sRunData.healthLevel = (UBYTE)(*((SDWORD *)pPos)); pPos += sizeof(SDWORD); } // load the droids while (members > 0) { endian_udword((UDWORD*)pPos); id = *((UDWORD *) pPos); psCDroid = (DROID *)getBaseObjFromId(id); if (!psCDroid) { debug(LOG_ERROR, "Could not find object id %d", id); } else { ((DROID_GROUP*)(psVal->v.oval))->add(psCDroid); } pPos += sizeof(UDWORD); members -= 1; } } else // a group var was unallocated during saving { pPos += sizeof(UWORD); } break; case ST_SOUND: // find audio id // don't use sound if it's disabled if (audio_Disabled()) { psVal->v.ival = NO_SOUND; break; } pName = pBuffer; index = audio_GetTrackID( pName ); if (index == SAMPLE_NOT_FOUND) { // find empty id and set track vals index = audio_SetTrackVals(pName, false, 100, 1800); if (!index) //this is a NON fatal error. { // We can't find filename of the sound for some reason. debug(LOG_ERROR, "Sound ID not available %s not found", pName); break; } } psVal->v.ival = index; break; case ST_STRUCTUREID: case ST_DROIDID: default: // just set the contents directly psVal->v.ival = *((SDWORD *)pBuffer); endian_sdword(&psVal->v.ival); break; } return true; }
// default value save routine //TODO: use union bool scrValDefSave(INTERP_VAL *psVal, char *pBuffer, UDWORD *pSize) { VIEWDATA *psIntMessage; const char *pName; RESEARCH *psResearch; char *pPos; DROID *psCDroid; switch ((unsigned)psVal->type) // Unsigned cast to suppress compiler warnings due to enum abuse. { case ST_INTMESSAGE: // save the name psIntMessage = (VIEWDATA *)psVal->v.oval; if (psIntMessage != NULL) { if (pBuffer) { strcpy(pBuffer, psIntMessage->pName); } *pSize = strlen(psIntMessage->pName)+1; } else { if (pBuffer) { *pBuffer = '\0'; } *pSize = 1; } break; case ST_BASEOBJECT: case ST_DROID: case ST_STRUCTURE: case ST_FEATURE: // just save the id if (pBuffer) { if (psVal->v.oval == NULL || ((BASE_OBJECT *)psVal->v.oval)->died > NOT_CURRENT_LIST) { *((UDWORD*)pBuffer) = UDWORD_MAX; } else { *((UDWORD*)pBuffer) = ((BASE_OBJECT *)psVal->v.oval)->id; } endian_udword((UDWORD*)pBuffer); } *pSize = sizeof(UDWORD); break; case ST_BASESTATS: case ST_COMPONENT: case ST_FEATURESTAT: case ST_STRUCTURESTAT: case ST_BODY: case ST_PROPULSION: case ST_ECM: case ST_SENSOR: case ST_CONSTRUCT: case ST_WEAPON: case ST_REPAIR: case ST_BRAIN: pName = scrGetStatName(psVal->type, psVal->v.ival); if (pName != NULL) { if (pBuffer) { strcpy(pBuffer, pName); } *pSize = strlen(pName) + 1; } else { return false; } break; case ST_TEMPLATE: if (pBuffer) { if (psVal->v.oval == NULL) { *((UDWORD*)pBuffer) = UDWORD_MAX; } else { *((UDWORD*)pBuffer) = ((DROID_TEMPLATE *)psVal->v.oval)->multiPlayerID; } endian_udword((UDWORD*)pBuffer); } *pSize = sizeof(UDWORD); break; case ST_TEXTSTRING: { const char * const idStr = psVal->v.sval ? strresGetIDfromString(psStringRes, psVal->v.sval) : NULL; uint16_t len = idStr ? strlen(idStr) + 1 : 0; if (pBuffer) { *((uint16_t*)pBuffer) = len; endian_uword((uint16_t*)pBuffer); memcpy(pBuffer + sizeof(len), idStr, len); } *pSize = sizeof(len) + len; break; } case ST_LEVEL: if (psVal->v.sval != NULL) { if (pBuffer) { strcpy(pBuffer, psVal->v.sval); } *pSize = strlen(psVal->v.sval)+1; } else { if (pBuffer) { *pBuffer = '\0'; } *pSize = 1; } break; case ST_RESEARCH: psResearch = (RESEARCH *)psVal->v.oval; if (psResearch != NULL) { if (pBuffer) { strcpy(pBuffer, psResearch->pName); } *pSize = strlen(psResearch->pName)+1; } else { if (pBuffer) { *pBuffer = '\0'; } *pSize = 1; } break; case ST_GROUP: { DROID_GROUP* const psGroup = (DROID_GROUP *)psVal->v.oval; const int members = psGroup ? psGroup->getNumMembers() : UNALLOCATED_OBJECT; if (pBuffer) { pPos = pBuffer; *((SDWORD *)pPos) = members; endian_sdword((SDWORD*)pPos); pPos += sizeof(SDWORD); if (psGroup) { // store the run data *((SDWORD *)pPos) = psGroup->sRunData.sPos.x; endian_sdword((SDWORD*)pPos); pPos += sizeof(SDWORD); *((SDWORD *)pPos) = psGroup->sRunData.sPos.y; endian_sdword((SDWORD*)pPos); pPos += sizeof(SDWORD); *((SDWORD *)pPos) = psGroup->sRunData.forceLevel; endian_sdword((SDWORD*)pPos); pPos += sizeof(SDWORD); *((SDWORD *)pPos) = psGroup->sRunData.leadership; endian_sdword((SDWORD*)pPos); pPos += sizeof(SDWORD); *((SDWORD *)pPos) = psGroup->sRunData.healthLevel; endian_sdword((SDWORD*)pPos); pPos += sizeof(SDWORD); // now store the droids for (psCDroid = psGroup->psList; psCDroid; psCDroid = psCDroid->psGrpNext) { checkValidId(psCDroid->id); *((UDWORD *)pPos) = psCDroid->id; endian_udword((UDWORD*)pPos); pPos += sizeof(UDWORD); } } } if (!psGroup) { *pSize = sizeof(SDWORD); } else { *pSize = sizeof(SDWORD) + sizeof(UDWORD) * members + sizeof(SDWORD) * 5; // members + runData } break; } case ST_SOUND: if(psVal->v.ival) { // can also return NULL pName = sound_GetTrackName((UDWORD)psVal->v.ival); } else { pName = NULL; } if (pName == NULL) { debug(LOG_WARNING, "scrValDefSave: couldn't get sound track name"); // just save an empty string pName = ""; } if (pBuffer) { strcpy(pBuffer, pName); } *pSize = strlen(pName) + 1; break; case ST_STRUCTUREID: case ST_DROIDID: // just save the variable contents directly if (pBuffer) { *((UDWORD *)pBuffer) = psVal->v.ival; endian_udword((UDWORD*)pBuffer); } *pSize = sizeof(UDWORD); break; default: ASSERT( false, "scrValDefSave: unknown script variable type for save" ); break; } return true; }