/* This file is part of Warzone 2100. Copyright (C) 1999-2004 Eidos Interactive Copyright (C) 2005-2007 Warzone Resurrection Project Warzone 2100 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Warzone 2100 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Warzone 2100; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * ScriptObj.c * * Object access functions for the script library * */ #include "lib/framework/frame.h" #include "objects.h" #include "lib/script/script.h" #include "scripttabs.h" #include "scriptobj.h" #include "group.h" #include "lib/gamelib/gtime.h" #include "cluster.h" #include "messagedef.h" #include "message.h" #include "researchdef.h" #include "lib/sound/audio.h" #include "audio_id.h" #include "multiplay.h" #include "text.h" #include "levels.h" #include "scriptvals.h" #include "research.h" // Get values from a base object BOOL scrBaseObjGet(UDWORD index) { // INTERP_VAL sVal; INTERP_TYPE type = 0; BASE_OBJECT *psObj; SDWORD val = 0; DROID *psDroid; STRUCTURE *psStruct; FEATURE *psFeature; if (!stackPopParams(1, ST_BASEOBJECT, &psObj)) { debug(LOG_ERROR, "scrBaseObjGet: stackPopParams failed"); return FALSE; } // Check this is a valid pointer if (psObj == NULL ) { debug(LOG_ERROR, "scrBaseObjGet: was passed an invalid pointer"); ASSERT( FALSE, "scrBaseObjGet: was passed an invalid pointer" ); return FALSE; } // Check this is a valid pointer if (psObj->type != OBJ_DROID && psObj->type != OBJ_STRUCTURE && psObj->type != OBJ_FEATURE) { debug(LOG_ERROR, "scrBaseObjGet: invalid object"); ASSERT( FALSE, "scrBaseObjGet: invalid object" ); return FALSE; } // set the type and return value switch (index) { case OBJID_POSX: type = VAL_INT; val = (SDWORD)psObj->x; break; case OBJID_POSY: type = VAL_INT; val = (SDWORD)psObj->y; break; case OBJID_POSZ: type = VAL_INT; val = (SDWORD)psObj->z; break; case OBJID_ID: type = VAL_INT; val = (SDWORD)psObj->id; break; case OBJID_PLAYER: type = VAL_INT; val = (SDWORD)psObj->player; break; case OBJID_TYPE: type = VAL_INT; val = (SDWORD)psObj->type; break; case OBJID_ORDER: if (psObj->type != OBJ_DROID) { debug(LOG_ERROR, "scrBaseObjGet: order only valid for a droid"); ASSERT( FALSE,"scrBaseObjGet: order only valid for a droid" ); return FALSE; } type = VAL_INT; val = (SDWORD)((DROID *)psObj)->order; if ((val == DORDER_GUARD) && (((DROID *)psObj)->psTarget == NULL)) { val = DORDER_NONE; } break; //new member variable case OBJID_ACTION: if (psObj->type != OBJ_DROID) { debug(LOG_ERROR, "scrBaseObjGet: action only valid for a droid"); ASSERT( FALSE,"scrBaseObjGet: action only valid for a droid" ); return FALSE; } type = VAL_INT; val = (SDWORD)((DROID *)psObj)->action; break; //new member variable - if droid is selected (humans only) case OBJID_SELECTED: if (psObj->type != OBJ_DROID) { debug(LOG_ERROR, "scrBaseObjGet: selected only valid for a droid"); ASSERT( FALSE,"scrBaseObjGet: selected only valid for a droid" ); return FALSE; } type = VAL_BOOL; val = (SDWORD)((DROID *)psObj)->selected; break; case OBJID_STRUCTSTATTYPE: if (psObj->type == OBJ_STRUCTURE) { type = VAL_INT; val = ((STRUCTURE *)psObj)->pStructureType->type; } else { debug(LOG_ERROR, ".stattype is only supported by Structures"); return FALSE; } break; case OBJID_ORDERX: if (psObj->type != OBJ_DROID) { debug(LOG_ERROR, "scrBaseObjGet: order only valid for a droid"); ASSERT( FALSE,"scrBaseObjGet: order only valid for a droid" ); return FALSE; } type = VAL_INT; val = (SDWORD)((DROID *)psObj)->orderX; break; case OBJID_ORDERY: if (psObj->type != OBJ_DROID) { debug(LOG_ERROR, "scrBaseObjGet: order only valid for a droid"); ASSERT( FALSE,"scrBaseObjGet: order only valid for a droid" ); return FALSE; } type = VAL_INT; val = (SDWORD)((DROID *)psObj)->orderY; break; case OBJID_DROIDTYPE: if (psObj->type != OBJ_DROID) { debug(LOG_ERROR, "scrBaseObjGet: droidType only valid for a droid"); ASSERT( FALSE,"scrBaseObjGet: droidType only valid for a droid" ); return FALSE; } type = VAL_INT; val = (SDWORD)((DROID *)psObj)->droidType; break; case OBJID_CLUSTERID: if (psObj->type == OBJ_FEATURE) { debug(LOG_ERROR, "scrBaseObjGet: clusterID not valid for features"); ASSERT( FALSE,"scrBaseObjGet: clusterID not valid for features" ); return FALSE; } type = VAL_INT; val = clustGetClusterID(psObj); break; case OBJID_HEALTH: switch (psObj->type) { case OBJ_DROID: psDroid = (DROID *)psObj; type = VAL_INT; val = psDroid->body * 100 / psDroid->originalBody; break; case OBJ_FEATURE: psFeature = (FEATURE *)psObj; type = VAL_INT; if (psFeature->psStats->damageable) { val = psFeature->body * 100 / psFeature->psStats->body; } else { val = 100; } break; case OBJ_STRUCTURE: psStruct = (STRUCTURE *)psObj; type = VAL_INT; //val = psStruct->body * 100 / psStruct->baseBodyPoints; val = psStruct->body * 100 / structureBody(psStruct); break; default: break; } break; case OBJID_BODY: if (psObj->type != OBJ_DROID) { debug(LOG_ERROR, "scrBaseObjGet: body only valid for a droid"); ASSERT( FALSE,"scrBaseObjGet: body only valid for a droid" ); return FALSE; } type = (INTERP_TYPE)ST_BODY; val = ((DROID *)psObj)->asBits[COMP_BODY].nStat; break; case OBJID_PROPULSION: if (psObj->type != OBJ_DROID) { debug(LOG_ERROR, "scrBaseObjGet: propulsion only valid for a droid"); ASSERT( FALSE,"scrBaseObjGet: propulsion only valid for a droid" ); return FALSE; } type = (INTERP_TYPE)ST_PROPULSION; val = ((DROID *)psObj)->asBits[COMP_PROPULSION].nStat; break; case OBJID_WEAPON: if (psObj->type != OBJ_DROID) { debug(LOG_ERROR, "scrBaseObjGet: weapon only valid for a droid"); ASSERT( FALSE,"scrBaseObjGet: weapon only valid for a droid" ); return FALSE; } type = (INTERP_TYPE)ST_WEAPON; //if (((DROID *)psObj)->numWeaps == 0) if (((DROID *)psObj)->asWeaps[0].nStat == 0) { val = 0; } else { val = ((DROID *)psObj)->asWeaps[0].nStat; } break; case OBJID_STRUCTSTAT: //droid.stat - now returns the type of structure a truck is building for droids if (psObj->type == OBJ_STRUCTURE) { type = ST_STRUCTURESTAT; val = ((STRUCTURE *)psObj)->pStructureType - asStructureStats; } else if (psObj->type == OBJ_DROID) { //psStructStats = (STRUCTURE_STATS*)psDroid->psTarStats; type = ST_STRUCTURESTAT; val = (SDWORD)((STRUCTURE_STATS *)(((DROID *)psObj)->psTarStats) - asStructureStats); } else //Nothing else supported { debug(LOG_ERROR, "scrBaseObjGet(): .stat only valid for structures and droids"); ASSERT( FALSE,"scrBaseObjGet(): .stat only valid for structures and droids" ); return FALSE; } break; case OBJID_TARGET: //added object->psTarget if (psObj->type == OBJ_STRUCTURE) { type = ST_BASEOBJECT; val = (SDWORD)((STRUCTURE *)psObj)->psTarget; } else if (psObj->type == OBJ_DROID) { //psStructStats = (STRUCTURE_STATS*)psDroid->psTarStats; type = ST_BASEOBJECT; val = (SDWORD)(((DROID *)psObj)->psTarget); } else //Nothing else supported { debug(LOG_ERROR, "scrBaseObjGet(): .target only valid for structures and droids"); ASSERT( FALSE,"scrBaseObjGet(): .target only valid for structures and droids" ); return FALSE; } break; default: debug(LOG_ERROR, "scrBaseObjGet: unknown variable index"); ASSERT( FALSE, "scrBaseObjGet: unknown variable index" ); return FALSE; break; } // Return the value if (!stackPushResult(type, val)) { debug(LOG_ERROR, "scrBaseObjGet: stackPushResult() failed"); return FALSE; } return TRUE; } // Set values from a base object BOOL scrBaseObjSet(UDWORD index) { index = index; return TRUE; } // convert a base object to a droid if it is the right type BOOL scrObjToDroid(void) { BASE_OBJECT *psObj; if (!stackPopParams(1, ST_BASEOBJECT, &psObj)) { return FALSE; } // return NULL if not a droid if (psObj->type != OBJ_DROID) { psObj = NULL; } if (!stackPushResult((INTERP_TYPE)ST_DROID, (SDWORD)psObj)) { return FALSE; } return TRUE; } // convert a base object to a structure if it is the right type BOOL scrObjToStructure(void) { BASE_OBJECT *psObj; if (!stackPopParams(1, ST_BASEOBJECT, &psObj)) { return FALSE; } // return NULL if not a droid if (psObj->type != OBJ_STRUCTURE) { psObj = NULL; } if (!stackPushResult((INTERP_TYPE)ST_STRUCTURE, (SDWORD)psObj)) { return FALSE; } return TRUE; } // convert a base object to a feature if it is the right type BOOL scrObjToFeature(void) { BASE_OBJECT *psObj; if (!stackPopParams(1, ST_BASEOBJECT, &psObj)) { return FALSE; } // return NULL if not a droid if (psObj->type != OBJ_FEATURE) { psObj = NULL; } if (!stackPushResult((INTERP_TYPE)ST_FEATURE, (SDWORD)psObj)) { return FALSE; } return TRUE; } // cache all the possible values for the last group to try // to speed up access static SDWORD lgX,lgY, lgMembers, lgHealth; // Get values from a group BOOL scrGroupObjGet(UDWORD index) { INTERP_TYPE type; DROID_GROUP *psGroup; SDWORD val; DROID *psCurr; if (!stackPopParams(1, ST_GROUP, &psGroup)) { return FALSE; } //fix: turn off caching, since it can screw up everything if returns outdated values // recalculate the values if necessary /* if (lgGameTime != gameTime || psScrLastGroup != psGroup) { lgGameTime = gameTime; psScrLastGroup = psGroup; lgMembers = 0; lgHealth = 0; lgX = lgY = 0; for(psCurr = psGroup->psList; psCurr; psCurr = psCurr->psGrpNext) { lgMembers += 1; lgX += (SDWORD)psCurr->x; lgY += (SDWORD)psCurr->y; lgHealth += (SDWORD)((100 * psCurr->body)/psCurr->originalBody); } if (lgMembers > 0) { lgX = lgX / lgMembers; lgY = lgY / lgMembers; lgHealth = lgHealth / lgMembers; } } */ switch (index) { case GROUPID_POSX: lgX = 0; lgMembers = 0; for(psCurr = psGroup->psList; psCurr; psCurr = psCurr->psGrpNext) { lgMembers += 1; lgX += (SDWORD)psCurr->x; } if (lgMembers > 0) { lgX = lgX / lgMembers; } type = VAL_INT; val = lgX; break; case GROUPID_POSY: lgY = 0; lgMembers = 0; for(psCurr = psGroup->psList; psCurr; psCurr = psCurr->psGrpNext) { lgMembers += 1; lgY += (SDWORD)psCurr->y; } if (lgMembers > 0) { lgY = lgY / lgMembers; } type = VAL_INT; val = lgY; break; case GROUPID_MEMBERS: lgMembers = 0; for(psCurr = psGroup->psList; psCurr; psCurr = psCurr->psGrpNext) { lgMembers += 1; } type = VAL_INT; val = lgMembers; break; case GROUPID_HEALTH: lgHealth = 0; lgMembers = 0; for(psCurr = psGroup->psList; psCurr; psCurr = psCurr->psGrpNext) { lgMembers += 1; lgHealth += (SDWORD)((100 * psCurr->body)/psCurr->originalBody); } if (lgMembers > 0) { lgHealth = lgHealth / lgMembers; } type = VAL_INT; val = lgHealth; break; default: ASSERT( FALSE, "scrGroupObjGet: unknown variable index" ); return FALSE; break; } // Return the value if (!stackPushResult(type, val)) { return FALSE; } return TRUE; } // get the name from a stat pointer STRING *scrGetStatName(INTERP_TYPE type, UDWORD data) { STRING *pName = NULL; switch (type) { case ST_STRUCTURESTAT: if (data < numStructureStats) { pName = asStructureStats[data].pName; } break; case ST_FEATURESTAT: if (data < numFeatureStats) { pName = asFeatureStats[data].pName; } break; case ST_BODY: if (data < numBodyStats) { pName = asBodyStats[data].pName; } break; case ST_PROPULSION: if (data < numPropulsionStats) { pName = asPropulsionStats[data].pName; } break; case ST_ECM: if (data < numECMStats) { pName = asECMStats[data].pName; } break; case ST_SENSOR: if (data < numSensorStats) { pName = asSensorStats[data].pName; } break; case ST_CONSTRUCT: if (data < numConstructStats) { pName = asConstructStats[data].pName; } break; case ST_WEAPON: if (data < numWeaponStats) { pName = asWeaponStats[data].pName; } break; case ST_REPAIR: if (data < numRepairStats) { pName = asRepairStats[data].pName; } break; case ST_BRAIN: if (data < numBrainStats) { pName = asBrainStats[data].pName; } break; case ST_BASESTATS: case ST_COMPONENT: // should never have variables of this type break; default: break; } if (pName == NULL) { debug( LOG_ERROR, "scrGetStatName: cannot get name for a base stat" ); abort(); } return pName; } // default value save routine BOOL scrValDefSave(INTERP_TYPE type, UDWORD data, char *pBuffer, UDWORD *pSize) { VIEWDATA *psIntMessage; STRING *pName; RESEARCH *psResearch; char *pPos; DROID *psCDroid; SDWORD members; DROID_GROUP *psGroup; #ifdef _DEBUG BASE_OBJECT *psObj; #endif switch (type) { case ST_INTMESSAGE: // save the name psIntMessage = (VIEWDATA *)data; if (psIntMessage != NULL) { if (pBuffer) { strcpy((char *)pBuffer, psIntMessage->pName); } *pSize = strlen(psIntMessage->pName)+1; } else { if (pBuffer) { *((UBYTE *)pBuffer) = 0; } *pSize = 1; } break; case ST_BASEOBJECT: case ST_DROID: case ST_STRUCTURE: case ST_FEATURE: // just save the id if (pBuffer) { if (data == 0) { *((UDWORD*)pBuffer) = UDWORD_MAX; } else { *((UDWORD*)pBuffer) = ((BASE_OBJECT *)data)->id; #ifdef _DEBUG psObj = getBaseObjFromId(((BASE_OBJECT *)data)->id); ASSERT( psObj == (BASE_OBJECT *)data,"scrValDefSave failed to find object, continue" ); #endif } } *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(type, data); if (pName != NULL) { if (pBuffer) { strcpy((char *)pBuffer, pName); } *pSize = strlen(pName) + 1; } else { return FALSE; } break; case ST_TEMPLATE: if (pBuffer) { if (data == 0) { *((UDWORD*)pBuffer) = UDWORD_MAX; } else { *((UDWORD*)pBuffer) = ((DROID_TEMPLATE *)data)->multiPlayerID; } } *pSize = sizeof(UDWORD); break; case ST_TEXTSTRING: if (pBuffer) { if (data == 0) { *((UDWORD*)pBuffer) = UDWORD_MAX; } else { *((UDWORD*)pBuffer) = strresGetIDfromString(psStringRes, (STRING *)data); } } *pSize = sizeof(UDWORD); break; case ST_LEVEL: if (data != 0) { if (pBuffer) { strcpy((char *)pBuffer, (STRING *)data); } *pSize = strlen((STRING *)data)+1; } else { if (pBuffer) { *((UBYTE *)pBuffer) = 0; } *pSize = 1; } break; case ST_RESEARCH: psResearch = (RESEARCH *)data; if (psResearch != NULL) { if (pBuffer) { strcpy((char *)pBuffer, psResearch->pName); } *pSize = strlen(psResearch->pName)+1; } else { if (pBuffer) { *((UBYTE *)pBuffer) = 0; } *pSize = 1; } break; case ST_GROUP: if (data != 0) { members = grpNumMembers((DROID_GROUP *)data); } else { members = 0; } if (pBuffer != NULL) { pPos = pBuffer; psGroup = (DROID_GROUP *)data; // store the run data *((SDWORD *)pPos) = psGroup->sRunData.sPos.x; pPos += sizeof(SDWORD); *((SDWORD *)pPos) = psGroup->sRunData.sPos.y; pPos += sizeof(SDWORD); *((SDWORD *)pPos) = psGroup->sRunData.forceLevel; pPos += sizeof(SDWORD); *((SDWORD *)pPos) = psGroup->sRunData.leadership; pPos += sizeof(SDWORD); *((SDWORD *)pPos) = psGroup->sRunData.healthLevel; pPos += sizeof(SDWORD); // now store the droids for(psCDroid=((DROID_GROUP *)data)->psList; psCDroid; psCDroid=psCDroid->psGrpNext) { checkValidId(psCDroid->id); *((UDWORD *)pPos) = psCDroid->id; pPos += sizeof(UDWORD); } } *pSize = sizeof(UDWORD) * members + sizeof(SDWORD) * 5; break; case ST_SOUND: /* pName = sound_GetTrackName((SDWORD)data); if (pName == NULL) { DBERROR(("scrValDefSave: couldn't get sound track name")); return FALSE; } if (pBuffer) { strcpy((char *)pBuffer, pName); } *pSize = strlen((char *)pName) + 1;*/ if (pBuffer) { *((UDWORD *) pBuffer) = sound_GetTrackHashName((SDWORD)data); } *pSize = sizeof(UDWORD); break; case ST_STRUCTUREID: case ST_DROIDID: default: ASSERT( (type == ST_STRUCTUREID) || (type == ST_DROIDID), "scrValDefSave: unknown script variable type for save" ); // just save the variable contents directly if (pBuffer) { *((UDWORD *)pBuffer) = data; } *pSize = sizeof(UDWORD); break; } return TRUE; } // default value load routine BOOL scrValDefLoad(SDWORD version, INTERP_TYPE type, char *pBuffer, UDWORD size, UDWORD *pData) { char *pPos; DROID *psCDroid; SDWORD index, members; UDWORD id; LEVEL_DATASET *psLevel; DROID_GROUP *psGroup; switch (type) { case ST_INTMESSAGE: if ((size == 1) && (*pBuffer == 0)) { *pData = 0; } else { *pData = (UDWORD)getViewData((STRING *)pBuffer); if (*pData == 0) { return FALSE; } } break; case ST_BASEOBJECT: case ST_DROID: case ST_STRUCTURE: case ST_FEATURE: id = *((UDWORD *)pBuffer); if (id == UDWORD_MAX) { *pData = 0; } else { if (!scrvGetBaseObj(*((UDWORD*)pBuffer), (BASE_OBJECT **)pData)) { debug( LOG_ERROR, "scrValDefLoad: couldn't find object id %d", *((UDWORD*)pBuffer) ); abort(); } } break; case ST_BASESTATS: case ST_COMPONENT: break; case ST_STRUCTURESTAT: index = getStructStatFromName((char *)pBuffer); if (index == -1) { debug( LOG_ERROR, "scrValDefLoad: couldn't find structure stat %s", pBuffer ); abort(); index = 0; } *pData = (UDWORD)index; break; case ST_FEATURESTAT: index = getFeatureStatFromName((char *)pBuffer); if (index == -1) { debug( LOG_ERROR, "scrValDefLoad: couldn't find feature stat %s", pBuffer ); abort(); index = 0; } *pData = (UDWORD)index; break; case ST_BODY: index = getCompFromResName(COMP_BODY, (char *)pBuffer); if (index == -1) { debug( LOG_ERROR, "scrValDefLoad: couldn't find body component %s", pBuffer ); abort(); index = 0; } *pData = (UDWORD)index; break; case ST_PROPULSION: index = getCompFromResName(COMP_PROPULSION, (char *)pBuffer); if (index == -1) { debug( LOG_ERROR, "scrValDefLoad: couldn't find propulsion component %s", pBuffer ); abort(); index = 0; } *pData = (UDWORD)index; break; case ST_ECM: index = getCompFromResName(COMP_ECM, (char *)pBuffer); if (index == -1) { debug( LOG_ERROR, "scrValDefLoad: couldn't find ECM component %s", pBuffer ); abort(); index = 0; } *pData = (UDWORD)index; break; case ST_SENSOR: index = getCompFromResName(COMP_SENSOR, (char *)pBuffer); if (index == -1) { debug( LOG_ERROR, "scrValDefLoad: couldn't find sensor component %s", pBuffer ); abort(); index = 0; } *pData = (UDWORD)index; break; case ST_CONSTRUCT: index = getCompFromResName(COMP_CONSTRUCT, (char *)pBuffer); if (index == -1) { debug( LOG_ERROR, "scrValDefLoad: couldn't find constructor component %s", pBuffer ); abort(); index = 0; } *pData = (UDWORD)index; break; case ST_WEAPON: index = getCompFromResName(COMP_WEAPON, (char *)pBuffer); if (index == -1) { debug( LOG_ERROR, "scrValDefLoad: couldn't find weapon %s", pBuffer ); abort(); index = 0; } *pData = (UDWORD)index; break; case ST_REPAIR: index = getCompFromResName(COMP_REPAIRUNIT, (char *)pBuffer); if (index == -1) { debug( LOG_ERROR, "scrValDefLoad: couldn't find repair component %s", pBuffer ); abort(); index = 0; } *pData = (UDWORD)index; break; case ST_BRAIN: index = getCompFromResName(COMP_BRAIN, (char *)pBuffer); if (index == -1) { debug( LOG_ERROR, "scrValDefLoad: couldn't find repair brain %s", pBuffer ); abort(); index = 0; } *pData = (UDWORD)index; break; case ST_TEMPLATE: id = *((UDWORD *)pBuffer); if (id == UDWORD_MAX) { *((DROID_TEMPLATE **)pData) = NULL; } else { *((DROID_TEMPLATE **)pData) = IdToTemplate(id, ANYPLAYER); if (*pData == 0) { debug( LOG_ERROR, "scrValDefLoad: couldn't find template id %d", *((UDWORD *)pBuffer) ); abort(); } } break; case ST_TEXTSTRING: if (*((UDWORD *)pBuffer) == UDWORD_MAX) { *pData = 0; } else { *pData = (UDWORD)(strresGetString(psStringRes, *((UDWORD *)pBuffer))); } break; case ST_LEVEL: if ((size == 1) && (*pBuffer == 0)) { *pData = 0; } else { if (!levFindDataSet((char *)pBuffer, &psLevel)) { debug( LOG_ERROR, "scrValDefLoad: couldn't find level dataset %s", pBuffer ); abort(); } *((STRING **)pData) = psLevel->pName; } break; case ST_RESEARCH: if ((size == 1) && (*pBuffer == 0)) { *pData = 0; } else { *pData = (UDWORD)getResearch((char *)pBuffer, TRUE); if (*pData == 0) { debug( LOG_ERROR, "scrValDefLoad: couldn't find research %s", pBuffer ); abort(); } } break; case ST_GROUP: if (*pData == 0) { if (!grpCreate((DROID_GROUP **)pData)) { debug( LOG_ERROR, "scrValDefLoad: out of memory" ); abort(); break; } grpJoin(*((DROID_GROUP **)pData), NULL); } if (version == 1) { members = size / sizeof(UDWORD); pPos = pBuffer; } else if (version == 2) { members = (size - sizeof(SDWORD)*4) / sizeof(UDWORD); pPos = pBuffer; // load the retreat data psGroup = *((DROID_GROUP **)pData); psGroup->sRunData.sPos.x = *((SDWORD *)pPos); pPos += sizeof(SDWORD); psGroup->sRunData.sPos.y = *((SDWORD *)pPos); pPos += sizeof(SDWORD); psGroup->sRunData.forceLevel = (UBYTE)(*((SDWORD *)pPos)); pPos += sizeof(SDWORD); psGroup->sRunData.leadership = (UBYTE)(*((SDWORD *)pPos)); pPos += sizeof(SDWORD); } else { members = (size - sizeof(SDWORD)*5) / sizeof(UDWORD); pPos = pBuffer; // load the retreat data psGroup = *((DROID_GROUP **)pData); psGroup->sRunData.sPos.x = *((SDWORD *)pPos); pPos += sizeof(SDWORD); psGroup->sRunData.sPos.y = *((SDWORD *)pPos); pPos += sizeof(SDWORD); psGroup->sRunData.forceLevel = (UBYTE)(*((SDWORD *)pPos)); pPos += sizeof(SDWORD); psGroup->sRunData.leadership = (UBYTE)(*((SDWORD *)pPos)); pPos += sizeof(SDWORD); psGroup->sRunData.healthLevel = (UBYTE)(*((SDWORD *)pPos)); pPos += sizeof(SDWORD); } // load the droids while (members > 0) { if (!scrvGetBaseObj(*((UDWORD*)pPos), (BASE_OBJECT **)&psCDroid)) { debug( LOG_ERROR, "scrValDefLoad: couldn't find object id %d", *((UDWORD*)pBuffer) ); abort(); } else { grpJoin(*((DROID_GROUP **)pData), psCDroid); } pPos += sizeof(UDWORD); members -= 1; } break; case ST_SOUND: // find audio id // don't use sound if it's disabled if (audio_Disabled()) { *pData = (UDWORD)NO_SOUND; break; } index = audio_GetTrackIDFromHash( *((UDWORD *)pBuffer) ); if (index == SAMPLE_NOT_FOUND) { // find empty id index = audio_GetAvailableID(); if (index == SAMPLE_NOT_ALLOCATED) { // We can't find filename of the sound for some reason. debug( LOG_ERROR, "Sound ID not available %s not found", pBuffer ); break; } // set track vals audio_SetTrackValsHashName( *((UDWORD *)pBuffer), FALSE, index, 100, 1, 1800, 0 ); } *pData = (UDWORD)index; break; case ST_STRUCTUREID: case ST_DROIDID: default: // just set the contents directly *pData = *((UDWORD *)pBuffer); break; } return TRUE; }