Logo Search packages:      
Sourcecode: warzone2100 version File versions

scriptobj.c

/*
      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 <string.h>

#include "lib/framework/frame.h"
#include "lib/framework/strres.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 "lib/sound/audio_id.h"

#include "multiplay.h"

#include "text.h"
#include "levels.h"
#include "scriptvals.h"
#include "research.h"

static INTERP_VAL scrFunctionResult;      //function return value to be pushed to stack

// Get values from a base object
BOOL scrBaseObjGet(UDWORD index)
{
      INTERP_TYPE       type = 0;
      BASE_OBJECT       *psObj;
      DROID             *psDroid;
      STRUCTURE         *psStruct;
      FEATURE                 *psFeature;
      SDWORD                  temp;

      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");
            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");
            return false;
      }

      // set the type and return value
      switch (index)
      {
      case OBJID_POSX:
            type = VAL_INT;
            scrFunctionResult.v.ival = (SDWORD)psObj->pos.x;
            break;
      case OBJID_POSY:
            type = VAL_INT;
            scrFunctionResult.v.ival = (SDWORD)psObj->pos.y;
            break;
      case OBJID_POSZ:
            type = VAL_INT;
            scrFunctionResult.v.ival = (SDWORD)psObj->pos.z;
            break;
      case OBJID_ID:
            type = VAL_INT;
            scrFunctionResult.v.ival = (SDWORD)psObj->id;
            break;
      case OBJID_PLAYER:
            type = VAL_INT;
            scrFunctionResult.v.ival = (SDWORD)psObj->player;
            break;
      case OBJID_TYPE:
            type = VAL_INT;
            scrFunctionResult.v.ival = (SDWORD)psObj->type;
            break;
      case OBJID_ORDER:
            if (psObj->type != OBJ_DROID)
            {
                  debug(LOG_ERROR, "scrBaseObjGet: order only valid for a droid");
                  return false;
            }
            type = VAL_INT;
            scrFunctionResult.v.ival = (SDWORD)((DROID *)psObj)->order;
            if (scrFunctionResult.v.ival == DORDER_GUARD && ((DROID *)psObj)->psTarget == NULL)
            {
                  scrFunctionResult.v.ival = DORDER_NONE;
            }
            break;
      //new member variable
      case OBJID_ACTION:
            if (psObj->type != OBJ_DROID)
            {
                  debug(LOG_ERROR, "scrBaseObjGet: action only valid for a droid");
                  return false;
            }
            type = VAL_INT;
            scrFunctionResult.v.ival = (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");
                  return false;
            }
            type = VAL_BOOL;
            scrFunctionResult.v.bval = (SDWORD)((DROID *)psObj)->selected;
            break;

      case OBJID_STRUCTSTATTYPE:
            if (psObj->type == OBJ_STRUCTURE)
            {
                  type = VAL_INT;
                  scrFunctionResult.v.ival = ((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");
                  return false;
            }
            type = VAL_INT;
            scrFunctionResult.v.ival = (SDWORD)((DROID *)psObj)->orderX;
            break;
      case OBJID_ORDERY:
            if (psObj->type != OBJ_DROID)
            {
                  debug(LOG_ERROR, "scrBaseObjGet: order only valid for a droid");
                  return false;
            }
            type = VAL_INT;
            scrFunctionResult.v.ival = (SDWORD)((DROID *)psObj)->orderY;
            break;
      case OBJID_DROIDTYPE:
            if (psObj->type != OBJ_DROID)
            {
                  debug(LOG_ERROR, "scrBaseObjGet: droidType only valid for a droid");
                  return false;
            }
            type = VAL_INT;
            scrFunctionResult.v.ival = (SDWORD)((DROID *)psObj)->droidType;
            break;
      case OBJID_CLUSTERID:
            if (psObj->type == OBJ_FEATURE)
            {
                  debug(LOG_ERROR, "scrBaseObjGet: clusterID not valid for features");
                  return false;
            }
            type = VAL_INT;
            scrFunctionResult.v.ival = clustGetClusterID(psObj);
            break;
      case OBJID_HEALTH:
            switch (psObj->type)
            {
            case OBJ_DROID:
                  psDroid = (DROID *)psObj;
                  type = VAL_INT;
                  scrFunctionResult.v.ival = psDroid->body * 100 / psDroid->originalBody;
                  break;
            case OBJ_FEATURE:
                  psFeature = (FEATURE *)psObj;
                  type = VAL_INT;
                  if (psFeature->psStats->damageable)
                  {
                        scrFunctionResult.v.ival = psFeature->body * 100 / psFeature->psStats->body;
                  }
                  else
                  {
                        scrFunctionResult.v.ival = 100;
                  }
                  break;
            case OBJ_STRUCTURE:
                  psStruct = (STRUCTURE *)psObj;
                  type = VAL_INT;
                  //val = psStruct->body * 100 / psStruct->baseBodyPoints;
                  scrFunctionResult.v.ival = 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");
                  return false;
            }
            type = (INTERP_TYPE)ST_BODY;
            scrFunctionResult.v.ival = (SDWORD)((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");
                  return false;
            }
            type = (INTERP_TYPE)ST_PROPULSION;
            scrFunctionResult.v.ival = (SDWORD)((DROID *)psObj)->asBits[COMP_PROPULSION].nStat;
            break;
      case OBJID_WEAPON:            //TODO: only returns first weapon now
            type = (INTERP_TYPE)ST_WEAPON;
            switch (psObj->type)
            {
            case OBJ_DROID:
                  if (((DROID *)psObj)->asWeaps[0].nStat == 0)
                  {
                        scrFunctionResult.v.ival = 0;
                  }else{
                        scrFunctionResult.v.ival = (SDWORD)((DROID *)psObj)->asWeaps[0].nStat;
                  }
                  break;
            case OBJ_STRUCTURE:
                  if (((STRUCTURE *)psObj)->numWeaps == 0 || ((STRUCTURE *)psObj)->asWeaps[0].nStat == 0)
                  {
                        scrFunctionResult.v.ival = 0;
                  }else{
                        scrFunctionResult.v.ival = (SDWORD)((STRUCTURE *)psObj)->asWeaps[0].nStat;
                  }
                  break;
            default:          //only droids and structures can have a weapon
                  debug(LOG_ERROR, "scrBaseObjGet: weapon only valid for droids and structures" );
                  return false;
                  break;
            }

            break;

      case OBJID_STRUCTSTAT:
            //droid.stat - now returns the type of structure a truck is building for droids
            if (psObj->type == OBJ_STRUCTURE)
            {
                  type = (INTERP_TYPE)ST_STRUCTURESTAT;
                  scrFunctionResult.v.ival = ((STRUCTURE *)psObj)->pStructureType - asStructureStats;
            }
            else if (psObj->type == OBJ_DROID)
            {
                  type = (INTERP_TYPE)ST_STRUCTURESTAT;
                  scrFunctionResult.v.ival = (SDWORD)((STRUCTURE_STATS *)(((DROID *)psObj)->psTarStats) - asStructureStats);
            }
            else        //Nothing else supported
            {
                  debug(LOG_ERROR, "scrBaseObjGet(): .stat only valid for structures and droids");
                  return false;
            }

            break;

      case OBJID_TARGET:
            //added object->psTarget
            if (psObj->type == OBJ_STRUCTURE)
            {
                  type = (INTERP_TYPE)ST_BASEOBJECT;
                  scrFunctionResult.v.oval = ((STRUCTURE *)psObj)->psTarget[0];
            }
            else if (psObj->type == OBJ_DROID)
            {
                  type = (INTERP_TYPE)ST_BASEOBJECT;
                  scrFunctionResult.v.oval = ((DROID *)psObj)->psTarget;
            }
            else        //Nothing else supported
            {
                  debug(LOG_ERROR, "scrBaseObjGet(): .target only valid for structures and droids");
                  return false;
            }

            break;
      case OBJID_GROUP:
            if (psObj->type != OBJ_DROID)
            {
                  debug(LOG_ERROR, "scrBaseObjGet: group only valid for a droid");
                  return false;
            }

            type = (INTERP_TYPE)ST_GROUP;
            scrFunctionResult.v.oval = ((DROID *)psObj)->psGroup;
            break;
      case OBJID_WEAP_SHORT_RANGE:

            type = VAL_INT;
            temp = -1;        // in case object has no weapon return -1

            if (psObj->type == OBJ_STRUCTURE)
            {
                  if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat].shortRange;
                  }
            }
            else if (psObj->type == OBJ_DROID)
            {
                  if(((DROID *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat].shortRange;
                  }
            }
            else
            {
                  debug(LOG_ERROR, "scrBaseObjGet(): shortRange: features don't have weapons");
                  return false;
            }

            scrFunctionResult.v.ival = temp;

            break;
      case OBJID_WEAP_LONG_RANGE:

            type = VAL_INT;
            temp = -1;        // in case object has no weapon return -1

            if (psObj->type == OBJ_STRUCTURE)
            {
                  if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat].longRange;
                  }
            }
            else if (psObj->type == OBJ_DROID)
            {
                  if(((DROID *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat].longRange;
                  }
            }
            else
            {
                  debug(LOG_ERROR, "scrBaseObjGet(): shortRange: features don't have weapons");
                  return false;
            }

            scrFunctionResult.v.ival = temp;

            break;
      case OBJID_WEAP_SHORT_HIT:
            type = VAL_INT;
            temp = -1;        // in case object has no weapon return -1

            if (psObj->type == OBJ_STRUCTURE)
            {
                  if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = weaponShortHit(&asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat], psObj->player);
                  }
            }
            else if (psObj->type == OBJ_DROID)
            {
                  if(((DROID *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = weaponShortHit(&asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat], psObj->player);
                  }
            }
            else
            {
                  debug(LOG_ERROR, "scrBaseObjGet(): shortHit: features don't have weapons");
                  return false;
            }

            scrFunctionResult.v.ival = temp;

            break;
      case OBJID_WEAP_LONG_HIT:

            type = VAL_INT;
            temp = -1;        // in case object has no weapon return -1

            if (psObj->type == OBJ_STRUCTURE)
            {
                  if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = weaponLongHit(&asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat], psObj->player);
                  }
            }
            else if (psObj->type == OBJ_DROID)
            {
                  if(((DROID *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = weaponLongHit(&asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat], psObj->player);
                  }
            }
            else
            {
                  debug(LOG_ERROR, "scrBaseObjGet(): shortHit: features don't have weapons");
                  return false;
            }

            scrFunctionResult.v.ival = temp;

            break;
      case OBJID_WEAP_DAMAGE:

            type = VAL_INT;
            temp = -1;        // in case object has no weapon return -1

            if (psObj->type == OBJ_STRUCTURE)
            {
                  if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = weaponDamage(&asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat], psObj->player);
                  }
            }
            else if (psObj->type == OBJ_DROID)
            {
                  if(((DROID *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = weaponDamage(&asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat], psObj->player);
                  }
            }
            else
            {
                  debug(LOG_ERROR, "scrBaseObjGet(): shortHit: features don't have weapons");
                  return false;
            }

            scrFunctionResult.v.ival = temp;

            break;
      case OBJID_WEAP_FIRE_PAUSE:

            type = VAL_INT;
            temp = -1;        // in case object has no weapon return -1

            if (psObj->type == OBJ_STRUCTURE)
            {
                  if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = weaponFirePause(&asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat], psObj->player);
                  }
            }
            else if (psObj->type == OBJ_DROID)
            {
                  if(((DROID *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = weaponFirePause(&asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat], psObj->player);
                  }
            }
            else
            {
                  debug(LOG_ERROR, "scrBaseObjGet(): shortHit: features don't have weapons");
                  return false;
            }

            scrFunctionResult.v.ival = temp;

            break;
      case OBJID_WEAP_RELOAD_TIME:

            type = VAL_INT;
            temp = -1;        // in case object has no weapon return -1

            if (psObj->type == OBJ_STRUCTURE)
            {
                  if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat].reloadTime;
                  }
            }
            else if (psObj->type == OBJ_DROID)
            {
                  if(((DROID *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat].reloadTime;
                  }
            }
            else
            {
                  debug(LOG_ERROR, "scrBaseObjGet(): shortHit: features don't have weapons");
                  return false;
            }

            scrFunctionResult.v.ival = temp;

            break;
      case OBJID_WEAP_NUM_ROUNDS:

            type = VAL_INT;
            temp = -1;        // in case object has no weapon return -1

            if (psObj->type == OBJ_STRUCTURE)
            {
                  if(((STRUCTURE *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = asWeaponStats[((STRUCTURE *)psObj)->asWeaps[0].nStat].numRounds;
                  }
            }
            else if (psObj->type == OBJ_DROID)
            {
                  if(((DROID *)psObj)->asWeaps[0].nStat > 0)
                  {
                        temp = asWeaponStats[((DROID *)psObj)->asWeaps[0].nStat].numRounds;
                  }
            }
            else
            {
                  debug(LOG_ERROR, "scrBaseObjGet(): shortHit: features don't have weapons");
                  return false;
            }

            scrFunctionResult.v.ival = temp;

            break;
      case OBJID_HITPOINTS:

            type = VAL_INT;

            switch (psObj->type)
            {
            case OBJ_DROID:
                  scrFunctionResult.v.ival = (SDWORD)((DROID *)psObj)->body;
                  break;

            case OBJ_STRUCTURE:
                  scrFunctionResult.v.ival = (SDWORD)((STRUCTURE *)psObj)->body;
                  break;

            case OBJ_FEATURE:
                  scrFunctionResult.v.ival = (SDWORD)((FEATURE *)psObj)->body;
                  break;

            default:
                  debug(LOG_ERROR, "scrBaseObjGet: unknown object type");
                  return false;
                  break;
            }

            break;
      case OBJID_ORIG_HITPOINTS:
            type = VAL_INT;

            switch (psObj->type)
            {
            case OBJ_DROID:
                  scrFunctionResult.v.ival = (SDWORD)((DROID *)psObj)->originalBody;
                  break;

            case OBJ_STRUCTURE:
                  scrFunctionResult.v.ival = (SDWORD)structureBody((STRUCTURE *)psObj);
                  break;

            case OBJ_FEATURE:
                  scrFunctionResult.v.ival = ((FEATURE *)psObj)->psStats->body;
                  break;

            default:
                  debug(LOG_ERROR, "scrBaseObjGet: unknown object type");
                  return false;
                  break;
            }

            break;
      default:
            debug(LOG_ERROR, "scrBaseObjGet: unknown variable index");
            return false;
            break;
      }

      // Return the value
      if (!stackPushResult(type, &scrFunctionResult))
      {
            debug(LOG_ERROR, "scrBaseObjGet: stackPushResult() failed");
            return false;
      }

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


      scrFunctionResult.v.oval = psObj;
      if (!stackPushResult((INTERP_TYPE)ST_DROID, &scrFunctionResult))
      {
            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;
      }

      scrFunctionResult.v.oval = psObj;
      if (!stackPushResult((INTERP_TYPE)ST_STRUCTURE, &scrFunctionResult))
      {
            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;
      }

      scrFunctionResult.v.oval = psObj;
      if (!stackPushResult((INTERP_TYPE)ST_FEATURE, &scrFunctionResult))
      {
            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;
      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->pos.x;
                  lgY += (SDWORD)psCurr->pos.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->pos.x;
            }

            if (lgMembers > 0)
            {
                  lgX = lgX / lgMembers;
            }
            type = VAL_INT;
            scrFunctionResult.v.ival = lgX;
            break;
      case GROUPID_POSY:
            lgY = 0;
            lgMembers = 0;
            for(psCurr = psGroup->psList; psCurr; psCurr = psCurr->psGrpNext)
            {
                  lgMembers += 1;
                  lgY += (SDWORD)psCurr->pos.y;
            }

            if (lgMembers > 0)
            {
                  lgY = lgY / lgMembers;
            }

            type = VAL_INT;
            scrFunctionResult.v.ival = lgY;
            break;
      case GROUPID_MEMBERS:
            lgMembers = 0;
            for(psCurr = psGroup->psList; psCurr; psCurr = psCurr->psGrpNext)
            {
                  lgMembers += 1;
            }

            type = VAL_INT;
            scrFunctionResult.v.ival = 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;
            scrFunctionResult.v.ival = lgHealth;
            break;
      case GROUPID_TYPE:
            type = VAL_INT;
            scrFunctionResult.v.ival = psGroup->type;
            break;
      case GROUPID_CMD:
            type = (INTERP_TYPE)ST_DROID;
            scrFunctionResult.v.oval = psGroup->psCommander;
            break;
      default:
            ASSERT( false, "scrGroupObjGet: unknown variable index" );
            return false;
            break;
      }

      // Return the value
      if (!stackPushResult(type, &scrFunctionResult))
      {
            return false;
      }

      return true;
}


// get the name from a stat pointer
static char *scrGetStatName(INTERP_TYPE type, UDWORD data)
{
      char  *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
//TODO: use union
BOOL scrValDefSave(INTERP_VAL *psVal, char *pBuffer, UDWORD *pSize)
{
      VIEWDATA    *psIntMessage;
      const char  *pName;
      RESEARCH    *psResearch;
      char        *pPos;
      DROID       *psCDroid;
      SDWORD            members;
      BOOL        bObjectDefined;
      DROID_GROUP *psGroup;
#ifdef _DEBUG
      BASE_OBJECT *psObj;
#endif

      switch (psVal->type)
      {
      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)
                  {
                        *((UDWORD*)pBuffer) = UDWORD_MAX;
                  }
                  else
                  {
                        *((UDWORD*)pBuffer) = ((BASE_OBJECT *)psVal->v.oval)->id;
#ifdef _DEBUG
                        psObj = getBaseObjFromId(((BASE_OBJECT *)psVal->v.oval)->id);
                        ASSERT( psObj == (BASE_OBJECT *)psVal->v.oval,"scrValDefSave failed to find object, continue" );
#endif
                  }

                  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:
            if (pBuffer)
            {
                  if (psVal->v.sval == NULL)
                  {
                        *((UDWORD*)pBuffer) = UDWORD_MAX;
                  }
                  else
                  {
                        *((UDWORD*)pBuffer) = strresGetIDfromString(psStringRes, psVal->v.sval);
                  }
                  endian_udword((UDWORD*)pBuffer);
            }
            *pSize = sizeof(UDWORD);
            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:
            bObjectDefined = (psVal->v.oval != NULL);

            if (bObjectDefined)
            {
                  members = grpNumMembers((DROID_GROUP *)psVal->v.oval);
            }
            else
            {
                  members = UNALLOCATED_OBJECT;
            }

            if (pBuffer)
            {
                  pPos = pBuffer;

                  *((SDWORD *)pPos) = members;
                  endian_sdword((SDWORD*)pPos);
                  pPos += sizeof(SDWORD);

                  if(bObjectDefined)
                  {
                        psGroup = (DROID_GROUP *)psVal->v.oval;

                        // 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=((DROID_GROUP *)psVal->v.oval)->psList; psCDroid; psCDroid=psCDroid->psGrpNext)
                        {
                              checkValidId(psCDroid->id);

                              *((UDWORD *)pPos) = psCDroid->id;
                              endian_udword((UDWORD*)pPos);

                              pPos += sizeof(UDWORD);
                        }
                  }
            }

            if(!bObjectDefined)
            {
                  *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;
}

/// default value load routine
01153 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 (psVal->type)
      {
      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, "scrValDefLoad: couldn't find object id %d", id );
                        abort();
                  }
            }
            break;
      case ST_BASESTATS:
      case ST_COMPONENT:
            break;
      case ST_STRUCTURESTAT:
            index = getStructStatFromName(pBuffer);
            if (index == -1)
            {
                  debug( LOG_ERROR, "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_ERROR, "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_ERROR, "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_ERROR, "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_ERROR, "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_ERROR, "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_ERROR, "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_ERROR, "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_ERROR, "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_ERROR, "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_ERROR, "scrValDefLoad: couldn't find template id %d", id );
                        abort();
                  }
            }
            break;
      case ST_TEXTSTRING:
            id = *((UDWORD *)pBuffer);
            endian_udword(&id);
            if (id == UDWORD_MAX)
            {
                  psVal->v.sval = '\0';
            }
            else
            {
                  psVal->v.sval = strresGetString(psStringRes, id);
            }
            break;
      case ST_LEVEL:
            if ((size == 1) &&
                  (*pBuffer == 0))
            {
                  psVal->v.sval = '\0';
            }
            else
            {
                  psLevel = levFindDataSet(pBuffer);
                  if (psLevel == NULL)
                  {
                        debug( LOG_ERROR, "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, true);
                  if (psVal->v.oval == NULL)
                  {
                        debug( LOG_ERROR, "scrValDefLoad: couldn't find research %s", pBuffer );
                        abort();
                  }
            }
            break;
      case ST_GROUP:
            bObjectDefined = true;

            if (psVal->v.oval == NULL)
            {
                  if (!grpCreate((DROID_GROUP**)&(psVal->v.oval)))
                  {
                        debug( LOG_ERROR, "scrValDefLoad: out of memory" );
                        abort();
                        break;
                  }
                  grpJoin((DROID_GROUP*)(psVal->v.oval), NULL);
            }

            pPos = pBuffer;

            switch (version)
            {
                  case 1:
                        members = size / sizeof(UDWORD);
                        break;
                  case 2:
                        members = (size - sizeof(SDWORD)*4) / sizeof(UDWORD);
                        break;
                  case 3:
                        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);
                        break;
                  default:
                        members = 0;
                        debug( LOG_ERROR, "scrValDefLoad: unsupported version %i", version);
            }

            // 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, "scrValDefLoad: couldn't find object id %d", id );
                              abort();
                        }
                        else
                        {
                              grpJoin((DROID_GROUP*)(psVal->v.oval), 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;
}

Generated by  Doxygen 1.6.0   Back to index