// 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; }
/// 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; }
// 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; }
// 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; }