Logo Search packages:      
Sourcecode: warzone2100 version File versions

function.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
*/
/*
 * Function.c
 *
 * Store function stats for the Structures etc.
 *
 */
#include "lib/framework/frame.h"
#include "lib/framework/strres.h"

#include "function.h"
#include "stats.h"
#include "structure.h"
#include "text.h"
#include "research.h"
#include "droid.h"
#include "group.h"

#include "multiplay.h"


//holder for all functions
FUNCTION **asFunctions;
UDWORD numFunctions;


typedef BOOL (*LoadFunction)(const char *pData);


/*Returns the Function type based on the string - used for reading in data */
static UDWORD functionType(const char* pType)
{
      if (!strcmp(pType, "Production"))
      {
            return PRODUCTION_TYPE;
      }
      if (!strcmp(pType, "Production Upgrade"))
      {
            return PRODUCTION_UPGRADE_TYPE;
      }
      if (!strcmp(pType, "Research"))
      {
            return RESEARCH_TYPE;
      }
      if (!strcmp(pType, "Research Upgrade"))
      {
            return RESEARCH_UPGRADE_TYPE;
      }
      if (!strcmp(pType, "Power Generator"))
      {
            return POWER_GEN_TYPE;
      }
      if (!strcmp(pType, "Resource"))
      {
            return RESOURCE_TYPE;
      }
      if (!strcmp(pType, "Repair Droid"))
      {
            return REPAIR_DROID_TYPE;
      }
      if (!strcmp(pType, "Weapon Upgrade"))
      {
            return WEAPON_UPGRADE_TYPE;
      }
      if (!strcmp(pType, "Wall Function"))
      {
            return WALL_TYPE;
      }
      if (!strcmp(pType, "Structure Upgrade"))
      {
            return STRUCTURE_UPGRADE_TYPE;
      }
      if (!strcmp(pType, "WallDefence Upgrade"))
      {
            return WALLDEFENCE_UPGRADE_TYPE;
      }
      if (!strcmp(pType, "Power Upgrade"))
      {
            return POWER_UPGRADE_TYPE;
      }
      if (!strcmp(pType, "Repair Upgrade"))
      {
            return REPAIR_UPGRADE_TYPE;
      }
      if (!strcmp(pType, "VehicleRepair Upgrade"))
      {
            return DROIDREPAIR_UPGRADE_TYPE;
      }
      if (!strcmp(pType, "VehicleECM Upgrade"))
      {
            return DROIDECM_UPGRADE_TYPE;
      }
      if (!strcmp(pType, "VehicleConst Upgrade"))
      {
            return DROIDCONST_UPGRADE_TYPE;
      }
      if (!strcmp(pType, "VehicleBody Upgrade"))
      {
            return DROIDBODY_UPGRADE_TYPE;
      }
      if (!strcmp(pType, "VehicleSensor Upgrade"))
      {
            return DROIDSENSOR_UPGRADE_TYPE;
      }
      if (!strcmp(pType, "ReArm"))
      {
            return REARM_TYPE;
      }
      if (!strcmp(pType, "ReArm Upgrade"))
      {
            return REARM_UPGRADE_TYPE;
      }

      ASSERT( false, "Unknown Function Type: %s", pType );
      return 0;
}

// Allocate storage for the name
static BOOL storeName(FUNCTION* pFunction, const char* pNameToStore)
{
      pFunction->pName = strdup(pNameToStore);
      if (pFunction->pName == NULL)
      {
            debug( LOG_ERROR, "Function Name - Out of memory" );
            abort();
            return false;
      }

      return true;
}


static BOOL loadProduction(const char *pData)
{
      PRODUCTION_FUNCTION*    psFunction;
      //UBYTE                             propType;
      char                          functionName[MAX_STR_LENGTH], bodySize[MAX_STR_LENGTH];
      UDWORD                              productionOutput;
      //char                              propulsionType[MAX_STR_LENGTH];
      //PROPULSION_TYPES*           pPropulsionType;
      //allocate storage

      psFunction = (PRODUCTION_FUNCTION *)malloc(sizeof(PRODUCTION_FUNCTION));
      if (psFunction == NULL)
      {
            debug( LOG_ERROR, "Production Function - Out of memory" );
            abort();
            return false;
      }
      memset(psFunction, 0, sizeof(PRODUCTION_FUNCTION));

      //store the pointer in the Function Array
      *asFunctions = (FUNCTION*)psFunction;
      psFunction->ref = REF_FUNCTION_START + numFunctions;
      numFunctions++;
      asFunctions++;

      //set the type of function
      psFunction->type = PRODUCTION_TYPE;

      //read the data in
      functionName[0] = '\0';
      //propulsionType[0] = '\0';
      bodySize[0] = '\0';
      sscanf(pData, "%[^','],%[^','],%d", functionName, bodySize,
            &productionOutput);

      //allocate storage for the name
      storeName((FUNCTION *)psFunction, functionName);

      //get the propulsion stats pointer
/*    pPropulsionType = asPropulsionTypes;
      psFunction->propulsionType = 0;
      for (i=0; i < numPropulsionTypes; i++)
      {
            //compare the names
            if (!strcmp(propulsionType, pPropulsionType->pName))
            {
                  psFunction->propulsionType = pPropulsionType;
                  break;
            }
            pPropulsionType++;
      }
      //if haven't found the propulsion type, then problem
      if (!psFunction->propulsionType)
      {
            DBERROR(("Unknown Propulsion Type"));
            return false;
      }
*/
      /*propType = getPropulsionType(propulsionType);
      if (propType == INVALID_PROP_TYPE)
      {
            DBERROR(("Unknown Propulsion Type - %s", propulsionType));
            return false;
      }
      psFunction->propulsionType = propType;*/

      if (!getBodySize(bodySize, (UBYTE*)&psFunction->capacity))
      {

            ASSERT( false, "loadProduction: unknown body size for %s",psFunction->pName );

            return false;
      }

      //check prod output < UWORD_MAX
      if (productionOutput < UWORD_MAX)
      {
            psFunction->productionOutput = (UWORD)productionOutput;
      }
      else
      {

            ASSERT( false, "loadProduction: production Output too big for %s",psFunction->pName );

            psFunction->productionOutput = 0;
      }

      return true;
}

static BOOL loadProductionUpgradeFunction(const char *pData)
{
      PRODUCTION_UPGRADE_FUNCTION*  psFunction;
      char                                      functionName[MAX_STR_LENGTH];
      UDWORD                                          factory, cyborg, vtol;
      UDWORD outputModifier;

      //allocate storage
      psFunction = (PRODUCTION_UPGRADE_FUNCTION *)malloc(sizeof
            (PRODUCTION_UPGRADE_FUNCTION));
      if (psFunction == NULL)
      {
            debug( LOG_ERROR, "Production Upgrade Function - Out of memory" );
            abort();
            return false;
      }
      memset(psFunction, 0, sizeof(PRODUCTION_UPGRADE_FUNCTION));

      //store the pointer in the Function Array
      *asFunctions = (FUNCTION *)psFunction;
      psFunction->ref = REF_FUNCTION_START + numFunctions;
      numFunctions++;
      asFunctions++;

      //set the type of function
      psFunction->type = PRODUCTION_UPGRADE_TYPE;

      //read the data in
      functionName[0] = '\0';
      sscanf(pData, "%[^','],%d,%d,%d,%d", functionName, &factory,
            &cyborg, &vtol,&outputModifier);


      psFunction->outputModifier=(UBYTE)outputModifier;
      //allocate storage for the name
      storeName((FUNCTION *)psFunction, functionName);

      //set the factory flags
      if (factory)
      {
            psFunction->factory = true;
      }
      else
      {
            psFunction->factory = false;
      }
      if (cyborg)
      {
            psFunction->cyborgFactory = true;
      }
      else
      {
            psFunction->cyborgFactory = false;
      }
      if (vtol)
      {
            psFunction->vtolFactory = true;
      }
      else
      {
            psFunction->vtolFactory = false;
      }

      //increment the number of upgrades
      //numProductionUpgrades++;
      return true;
}

static BOOL loadResearchFunction(const char *pData)
{
      RESEARCH_FUNCTION*                  psFunction;
      char                                functionName[MAX_STR_LENGTH];

      //allocate storage
      psFunction = (RESEARCH_FUNCTION *)malloc(sizeof(RESEARCH_FUNCTION));
      if (psFunction == NULL)
      {
            debug( LOG_ERROR, "Research Function - Out of memory" );
            abort();
            return false;
      }
      memset(psFunction, 0, sizeof(RESEARCH_FUNCTION));

      //store the pointer in the Function Array
      *asFunctions = (FUNCTION *)psFunction;
      psFunction->ref = REF_FUNCTION_START + numFunctions;
      numFunctions++;
      asFunctions++;

      //set the type of function
      psFunction->type = RESEARCH_TYPE;

      //read the data in
      functionName[0] = '\0';
      sscanf(pData, "%[^','],%d", functionName, &psFunction->researchPoints);

      //allocate storage for the name
      storeName((FUNCTION *)psFunction, functionName);

      return true;
}

static BOOL loadReArmFunction(const char *pData)
{
      REARM_FUNCTION*                     psFunction;
      char                                functionName[MAX_STR_LENGTH];

      //allocate storage
      psFunction = (REARM_FUNCTION *)malloc(sizeof(REARM_FUNCTION));
      if (psFunction == NULL)
      {
            debug( LOG_ERROR, "ReArm Function - Out of memory" );
            abort();
            return false;
      }
      memset(psFunction, 0, sizeof(REARM_FUNCTION));

      //store the pointer in the Function Array
      *asFunctions = (FUNCTION *)psFunction;
      psFunction->ref = REF_FUNCTION_START + numFunctions;
      numFunctions++;
      asFunctions++;

      //set the type of function
      psFunction->type = REARM_TYPE;

      //read the data in
      functionName[0] = '\0';
      sscanf(pData, "%[^','],%d", functionName, &psFunction->reArmPoints);

      //allocate storage for the name
      storeName((FUNCTION *)psFunction, functionName);

      return true;
}


//generic load function for upgrade type
static BOOL loadUpgradeFunction(const char *pData, UBYTE type)
{
      char                                functionName[MAX_STR_LENGTH];
      UDWORD                                    modifier;
      UPGRADE_FUNCTION              *psFunction;

      //allocate storage
      psFunction = (UPGRADE_FUNCTION *)malloc(sizeof(UPGRADE_FUNCTION));
      if (psFunction == NULL)
      {
            debug( LOG_ERROR, "Upgrade Function - Out of memory" );
            abort();
            return false;
      }
      memset(psFunction, 0, sizeof(UPGRADE_FUNCTION));

      //store the pointer in the Function Array
      *asFunctions = (FUNCTION *)psFunction;
      psFunction->ref = REF_FUNCTION_START + numFunctions;
      numFunctions++;
      asFunctions++;

      //set the type of function
      psFunction->type = type;

      //read the data in
      functionName[0] = '\0';
      sscanf(pData, "%[^','],%d", functionName, &modifier);

      //allocate storage for the name
      storeName((FUNCTION *)psFunction, functionName);

      if (modifier > UWORD_MAX)
      {
            ASSERT( false, "loadUpgradeFunction: modifier too great for %s", functionName );
            return false;
      }

      //store the % upgrade
      psFunction->upgradePoints = (UWORD)modifier;

      return true;
}



static BOOL loadResearchUpgradeFunction(const char *pData)
{
      return loadUpgradeFunction(pData, RESEARCH_UPGRADE_TYPE);
}

static BOOL loadPowerUpgradeFunction(const char *pData)
{
      return loadUpgradeFunction(pData, POWER_UPGRADE_TYPE);
}

static BOOL loadRepairUpgradeFunction(const char *pData)
{
      return loadUpgradeFunction(pData, REPAIR_UPGRADE_TYPE);
}

static BOOL loadDroidRepairUpgradeFunction(const char *pData)
{
      return loadUpgradeFunction(pData, DROIDREPAIR_UPGRADE_TYPE);
}

static BOOL loadDroidECMUpgradeFunction(const char *pData)
{
      return loadUpgradeFunction(pData, DROIDECM_UPGRADE_TYPE);
}

static BOOL loadDroidConstUpgradeFunction(const char *pData)
{
      return loadUpgradeFunction(pData, DROIDCONST_UPGRADE_TYPE);
}

static BOOL loadReArmUpgradeFunction(const char *pData)
{
      return loadUpgradeFunction(pData, REARM_UPGRADE_TYPE);
}


static BOOL loadDroidBodyUpgradeFunction(const char *pData)
{
      DROIDBODY_UPGRADE_FUNCTION          *psFunction;
      char                                      functionName[MAX_STR_LENGTH];
      UDWORD                                          modifier, armourKinetic, armourHeat,
                                                      body, droid, cyborg;

      //allocate storage
      psFunction = (DROIDBODY_UPGRADE_FUNCTION *)malloc(
            sizeof(DROIDBODY_UPGRADE_FUNCTION));
      if (psFunction == NULL)
      {
            debug( LOG_ERROR, "UnitBody Upgrade Function - Out of memory" );
            abort();
            return false;
      }
      memset(psFunction, 0, sizeof(DROIDBODY_UPGRADE_FUNCTION));

      //store the pointer in the Function Array
      *asFunctions = (FUNCTION *)psFunction;
      psFunction->ref = REF_FUNCTION_START + numFunctions;
      numFunctions++;
      asFunctions++;

      //set the type of function
      psFunction->type = DROIDBODY_UPGRADE_TYPE;

      //read the data in
      functionName[0] = '\0';
      sscanf(pData, "%[^','],%d,%d,%d,%d,%d,%d", functionName, &modifier,
            &body, &armourKinetic,  &armourHeat, &droid, &cyborg);

      //allocate storage for the name
      storeName((FUNCTION *)psFunction, functionName);

      if (modifier > UWORD_MAX || armourKinetic > UWORD_MAX ||
            armourHeat > UWORD_MAX || body > UWORD_MAX)
      {
            ASSERT( false,
                  "loadUnitBodyUpgradeFunction: one or more modifiers too great" );
            return false;
      }

      //store the % upgrades
      psFunction->upgradePoints = (UWORD)modifier;
      psFunction->body = (UWORD)body;
      psFunction->armourValue[WC_KINETIC] = (UWORD)armourKinetic;
      psFunction->armourValue[WC_HEAT] = (UWORD)armourHeat;
      if (droid)
      {
            psFunction->droid = true;
      }
      else
      {
            psFunction->droid = false;
      }
      if (cyborg)
      {
            psFunction->cyborg = true;
      }
      else
      {
            psFunction->cyborg = false;
      }

      return true;
}

static BOOL loadDroidSensorUpgradeFunction(const char *pData)
{
      DROIDSENSOR_UPGRADE_FUNCTION  *psFunction;
      char                                      functionName[MAX_STR_LENGTH];
      UDWORD                                          modifier, range;

      //allocate storage
      psFunction = (DROIDSENSOR_UPGRADE_FUNCTION *)malloc(
            sizeof(DROIDSENSOR_UPGRADE_FUNCTION));
      if (psFunction == NULL)
      {
            debug( LOG_ERROR, "UnitSensor Upgrade Function - Out of memory" );
            abort();
            return false;
      }
      memset(psFunction, 0, sizeof(DROIDSENSOR_UPGRADE_FUNCTION));

      //store the pointer in the Function Array
      *asFunctions = (FUNCTION *)psFunction;
      psFunction->ref = REF_FUNCTION_START + numFunctions;
      numFunctions++;
      asFunctions++;

      //set the type of function
      psFunction->type = DROIDSENSOR_UPGRADE_TYPE;

      //read the data in
      functionName[0] = '\0';
      sscanf(pData, "%[^','],%d,%d", functionName, &modifier, &range);

      //allocate storage for the name
      storeName((FUNCTION *)psFunction, functionName);

      if (modifier > UWORD_MAX || range > UWORD_MAX)
      {
            ASSERT( false,
                  "loadUnitSensorUpgradeFunction: one or more modifiers too great" );
            return false;
      }

      //store the % upgrades
      psFunction->upgradePoints = (UWORD)modifier;
      psFunction->range = (UWORD)range;

    return true;
}

static BOOL loadWeaponUpgradeFunction(const char *pData)
{
      WEAPON_UPGRADE_FUNCTION*      psFunction;
      char                                functionName[MAX_STR_LENGTH],
                                                weaponSubClass[MAX_STR_LENGTH];
      UDWORD                                    firePause, shortHit, longHit, damage,
                                                radiusDamage, incenDamage, radiusHit;

      //allocate storage
      psFunction = (WEAPON_UPGRADE_FUNCTION *)malloc(sizeof
            (WEAPON_UPGRADE_FUNCTION));
      if (psFunction == NULL)
      {
            debug( LOG_ERROR, "Weapon Upgrade Function - Out of memory" );
            abort();
            return false;
      }
      memset(psFunction, 0, sizeof(WEAPON_UPGRADE_FUNCTION));

      //store the pointer in the Function Array
      *asFunctions = (FUNCTION *)psFunction;
      psFunction->ref = REF_FUNCTION_START + numFunctions;
      numFunctions++;
      asFunctions++;

      //set the type of function
      psFunction->type = WEAPON_UPGRADE_TYPE;

      //read the data in
      functionName[0] = '\0';
      weaponSubClass[0] = '\0';
      sscanf(pData, "%[^','],%[^','],%d,%d,%d,%d,%d,%d,%d", functionName,
            weaponSubClass, &firePause, &shortHit, &longHit, &damage, &radiusDamage,
            &incenDamage, &radiusHit);

      //allocate storage for the name
      storeName((FUNCTION *)psFunction, functionName);

      psFunction->subClass = getWeaponSubClass(weaponSubClass);
      if (psFunction->subClass == INVALID_SUBCLASS)
      {
            return false;
      }

      //check none of the %increases are over UBYTE max
      if (firePause > UBYTE_MAX ||
            shortHit > UWORD_MAX ||
            longHit > UWORD_MAX ||
            damage > UWORD_MAX ||
            radiusDamage > UWORD_MAX ||
            incenDamage > UWORD_MAX ||
            radiusHit > UWORD_MAX)
      {
            debug( LOG_ERROR, "A percentage increase for Weapon Upgrade function is too large" );
            abort();
            return false;
      }

      //copy the data across
      psFunction->firePause = (UBYTE)firePause;
      psFunction->shortHit = (UWORD)shortHit;
      psFunction->longHit = (UWORD)longHit;
      psFunction->damage = (UWORD)damage;
      psFunction->radiusDamage = (UWORD)radiusDamage;
      psFunction->incenDamage = (UWORD)incenDamage;
      psFunction->radiusHit = (UWORD)radiusHit;

      //increment the number of upgrades
      //numWeaponUpgrades++;

    return true;
}

static BOOL loadStructureUpgradeFunction(const char *pData)
{
      STRUCTURE_UPGRADE_FUNCTION  *psFunction;
      char                                functionName[MAX_STR_LENGTH];
      UDWORD                                    armour, body, resistance;

      //allocate storage
      psFunction = (STRUCTURE_UPGRADE_FUNCTION *)malloc(sizeof
            (STRUCTURE_UPGRADE_FUNCTION));
      if (psFunction == NULL)
      {
            debug( LOG_ERROR, "Structure Upgrade Function - Out of memory" );
            abort();
            return false;
      }
      memset(psFunction, 0, sizeof(STRUCTURE_UPGRADE_FUNCTION));

      //store the pointer in the Function Array
      *asFunctions = (FUNCTION *)psFunction;
      psFunction->ref = REF_FUNCTION_START + numFunctions;
      numFunctions++;
      asFunctions++;

      //set the type of function
      psFunction->type = STRUCTURE_UPGRADE_TYPE;

      //read the data in
      functionName[0] = '\0';
      sscanf(pData, "%[^','],%d,%d,%d", functionName, &armour, &body, &resistance);

      //allocate storage for the name
      storeName((FUNCTION *)psFunction, functionName);

      //check none of the %increases are over UWORD max
      if (armour > UWORD_MAX ||
            body > UWORD_MAX ||
            resistance > UWORD_MAX)
      {
            debug( LOG_ERROR, "A percentage increase for Structure Upgrade function is too large" );
            abort();
            return false;
      }

      //copy the data across
      psFunction->armour = (UWORD)armour;
      psFunction->body = (UWORD)body;
      psFunction->resistance = (UWORD)resistance;

      return true;
}

static BOOL loadWallDefenceUpgradeFunction(const char *pData)
{
      WALLDEFENCE_UPGRADE_FUNCTION  *psFunction;
      char                                functionName[MAX_STR_LENGTH];
      UDWORD                                    armour, body;

      //allocate storage
      psFunction = (WALLDEFENCE_UPGRADE_FUNCTION *)malloc(sizeof
            (WALLDEFENCE_UPGRADE_FUNCTION));
      if (psFunction == NULL)
      {
            debug( LOG_ERROR, "WallDefence Upgrade Function - Out of memory" );
            abort();
            return false;
      }
      memset(psFunction, 0, sizeof(WALLDEFENCE_UPGRADE_FUNCTION));

      //store the pointer in the Function Array
      *asFunctions = (FUNCTION *)psFunction;
      psFunction->ref = REF_FUNCTION_START + numFunctions;
      numFunctions++;
      asFunctions++;

      //set the type of function
      psFunction->type = WALLDEFENCE_UPGRADE_TYPE;

      //read the data in
      functionName[0] = '\0';
      sscanf(pData, "%[^','],%d,%d", functionName, &armour, &body);

      //allocate storage for the name
      storeName((FUNCTION *)psFunction, functionName);

      //check none of the %increases are over UWORD max
      if (armour > UWORD_MAX ||
            body > UWORD_MAX)
      {
            debug( LOG_ERROR, "A percentage increase for WallDefence Upgrade function is too large" );
            abort();
            return false;
      }

      //copy the data across
      psFunction->armour = (UWORD)armour;
      psFunction->body = (UWORD)body;

      return true;
}


static BOOL loadPowerGenFunction(const char *pData)
{
      POWER_GEN_FUNCTION*                 psFunction;
      char                                functionName[MAX_STR_LENGTH];

      //allocate storage
      psFunction = (POWER_GEN_FUNCTION *)malloc(sizeof
            (POWER_GEN_FUNCTION));
      if (psFunction == NULL)
      {
            debug( LOG_ERROR, "Power Gen Function - Out of memory" );
            abort();
            return false;
      }
      memset(psFunction, 0, sizeof(POWER_GEN_FUNCTION));

      //store the pointer in the Function Array
      *asFunctions = (FUNCTION *)psFunction;
      psFunction->ref = REF_FUNCTION_START + numFunctions;
      numFunctions++;
      asFunctions++;

      //set the type of function
      psFunction->type = POWER_GEN_TYPE;

      //read the data in
      functionName[0] = '\0';
      sscanf(pData, "%[^','],%d,%d,%d,%d,%d,%d", functionName,
            &psFunction->powerOutput, &psFunction->powerMultiplier,
            &psFunction->criticalMassChance, &psFunction->criticalMassRadius,
            &psFunction->criticalMassDamage, &psFunction->radiationDecayTime);


      if(bMultiPlayer)
      {
            modifyResources(psFunction);
      }


      //allocate storage for the name
      storeName((FUNCTION *)psFunction, functionName);

      return true;
}

static BOOL loadResourceFunction(const char *pData)
{
      RESOURCE_FUNCTION             *psFunction;
      char                                functionName[MAX_STR_LENGTH];

      //allocate storage
      psFunction = (RESOURCE_FUNCTION *)malloc(sizeof
            (RESOURCE_FUNCTION));
      if (psFunction == NULL)
      {
            debug( LOG_ERROR, "Resource Function - Out of memory" );
            abort();
            return false;
      }
      memset(psFunction, 0, sizeof(RESOURCE_FUNCTION));

      //store the pointer in the Function Array
      *asFunctions = (FUNCTION *)psFunction;
      psFunction->ref = REF_FUNCTION_START + numFunctions;
      numFunctions++;
      asFunctions++;

      //set the type of function
      psFunction->type = RESOURCE_TYPE;

      //read the data in
      functionName[0] = '\0';
      sscanf(pData, "%[^','],%d", functionName, &psFunction->maxPower);

      //allocate storage for the name
      storeName((FUNCTION *)psFunction, functionName);

      return true;
}


static BOOL loadRepairDroidFunction(const char *pData)
{
      REPAIR_DROID_FUNCTION*        psFunction;
      char                                functionName[MAX_STR_LENGTH];

      //allocate storage
      psFunction = (REPAIR_DROID_FUNCTION *)malloc(sizeof
            (REPAIR_DROID_FUNCTION));
      if (psFunction == NULL)
      {
            debug( LOG_ERROR, "Repair Droid Function - Out of memory" );
            abort();
            return false;
      }
      memset(psFunction, 0, sizeof(REPAIR_DROID_FUNCTION));

      //store the pointer in the Function Array
      *asFunctions = (FUNCTION *)psFunction;
      psFunction->ref = REF_FUNCTION_START + numFunctions;
      numFunctions++;
      asFunctions++;

      //set the type of function
      psFunction->type = REPAIR_DROID_TYPE;

      //read the data in
      functionName[0] = '\0';
      sscanf(pData, "%[^','],%d", functionName,
            &psFunction->repairPoints);

      //allocate storage for the name
      storeName((FUNCTION *)psFunction, functionName);

      return true;
}


/*loads the corner stat to use for a particular wall stat */
static BOOL loadWallFunction(const char *pData)
{
      WALL_FUNCTION                 *psFunction;
//    UDWORD                              i;
      char                          functionName[MAX_STR_LENGTH];
      char                          structureName[MAX_STR_LENGTH];
//    STRUCTURE_STATS               *pStructStat;

      //allocate storage
      psFunction = (WALL_FUNCTION *)malloc(sizeof(WALL_FUNCTION));
      if (psFunction == NULL)
      {
            debug( LOG_ERROR, "Wall Function - Out of memory" );
            abort();
            return false;
      }
      memset(psFunction, 0, sizeof(WALL_FUNCTION));

      //store the pointer in the Function Array
      *asFunctions = (FUNCTION*)psFunction;
      psFunction->ref = REF_FUNCTION_START + numFunctions;
      numFunctions++;
      asFunctions++;

      //set the type of function
      psFunction->type = WALL_TYPE;

      //read the data in
      functionName[0] = '\0';
      structureName[0] = '\0';
      sscanf(pData, "%[^','],%[^','],%*d", functionName, structureName);

      //allocate storage for the name
      storeName((FUNCTION *)psFunction, functionName);

      //store the structure name - cannot set the stat pointer here because structures
      //haven't been loaded in yet!
      if (!allocateName(&psFunction->pStructName, structureName))
      {
            debug( LOG_ERROR, "Structure Stats Invalid for function - %s", functionName );
            abort();
            return false;
      }
      psFunction->pCornerStat = NULL;

      return true;
}

void productionUpgrade(FUNCTION *pFunction, UBYTE player)
{
      PRODUCTION_UPGRADE_FUNCTION         *pUpgrade;

      pUpgrade = (PRODUCTION_UPGRADE_FUNCTION   *)pFunction;

      //check upgrades increase all values
      if (pUpgrade->factory)
      {
            if (asProductionUpgrade[player][FACTORY_FLAG].modifier <
                  pUpgrade->outputModifier)
            {
                  asProductionUpgrade[player][FACTORY_FLAG].modifier =
                        pUpgrade->outputModifier;
            }
      }
      if (pUpgrade->cyborgFactory)
      {
            if (asProductionUpgrade[player][CYBORG_FLAG].modifier <
                  pUpgrade->outputModifier)
            {
                  asProductionUpgrade[player][CYBORG_FLAG].modifier =
                        pUpgrade->outputModifier;
            }
      }
      if (pUpgrade->vtolFactory)
      {
            if (asProductionUpgrade[player][VTOL_FLAG].modifier <
                  pUpgrade->outputModifier)
            {
                  asProductionUpgrade[player][VTOL_FLAG].modifier =
                        pUpgrade->outputModifier;
            }
      }
}

void researchUpgrade(FUNCTION *pFunction, UBYTE player)
{
      RESEARCH_UPGRADE_FUNCTION           *pUpgrade;

      pUpgrade = (RESEARCH_UPGRADE_FUNCTION     *)pFunction;

      //check upgrades increase all values
      if (asResearchUpgrade[player].modifier < pUpgrade->upgradePoints)
      {
            asResearchUpgrade[player].modifier = pUpgrade->upgradePoints;
      }
}

void repairFacUpgrade(FUNCTION *pFunction, UBYTE player)
{
      REPAIR_UPGRADE_FUNCTION       *pUpgrade;

      pUpgrade = (REPAIR_UPGRADE_FUNCTION *)pFunction;

      //check upgrades increase all values
      if (asRepairFacUpgrade[player].modifier < pUpgrade->upgradePoints)
      {
            asRepairFacUpgrade[player].modifier = pUpgrade->upgradePoints;
      }
}

void powerUpgrade(FUNCTION *pFunction, UBYTE player)
{
      POWER_UPGRADE_FUNCTION        *pUpgrade;

      pUpgrade = (POWER_UPGRADE_FUNCTION  *)pFunction;

      //check upgrades increase all values
      if (asPowerUpgrade[player].modifier < pUpgrade->upgradePoints)
      {
            asPowerUpgrade[player].modifier = pUpgrade->upgradePoints;
      }
}

void reArmUpgrade(FUNCTION *pFunction, UBYTE player)
{
      REARM_UPGRADE_FUNCTION        *pUpgrade;

      pUpgrade = (REARM_UPGRADE_FUNCTION *)pFunction;

      //check upgrades increase all values
      if (asReArmUpgrade[player].modifier < pUpgrade->upgradePoints)
      {
            asReArmUpgrade[player].modifier = pUpgrade->upgradePoints;
      }
}

void structureBodyUpgrade(FUNCTION *pFunction, STRUCTURE *psBuilding)
{
      UWORD increase, prevBaseBody, newBaseBody;

      switch(psBuilding->pStructureType->type)
      {
      case REF_WALL:
      case REF_WALLCORNER:
      case REF_DEFENSE:
      case REF_BLASTDOOR:
            increase = ((WALLDEFENCE_UPGRADE_FUNCTION *)pFunction)->body;
            break;
      default:
            increase = ((STRUCTURE_UPGRADE_FUNCTION *)pFunction)->body;
            break;
      }

      prevBaseBody = (UWORD)structureBody(psBuilding);
      //newBaseBody = (UWORD)(psBuilding->pStructureType->bodyPoints + (psBuilding->
      //    pStructureType->bodyPoints * increase) / 100);
      newBaseBody = (UWORD)(structureBaseBody(psBuilding) +
            (structureBaseBody(psBuilding) * increase) / 100);

      if (newBaseBody > prevBaseBody)
      {
            psBuilding->body = (UWORD)((psBuilding->body * newBaseBody) / prevBaseBody);
            //psBuilding->baseBodyPoints = newBaseBody;
      }
}

void structureArmourUpgrade(FUNCTION *pFunction, STRUCTURE *psBuilding)
{
      UWORD increase, prevBaseArmour, newBaseArmour, i, j;

      switch(psBuilding->pStructureType->type)
      {
      case REF_WALL:
      case REF_WALLCORNER:
      case REF_DEFENSE:
      case REF_BLASTDOOR:
            increase = ((WALLDEFENCE_UPGRADE_FUNCTION *)pFunction)->armour;
            break;
      default:
            increase = ((STRUCTURE_UPGRADE_FUNCTION *)pFunction)->armour;
            break;
      }

      prevBaseArmour = (UWORD)structureArmour(psBuilding->pStructureType, psBuilding->player);
      newBaseArmour = (UWORD)(psBuilding->pStructureType->armourValue + (psBuilding->
            pStructureType->armourValue * increase) / 100);

      if (newBaseArmour > prevBaseArmour)
      {
            // TODO: support advanced armour system
            for (i = 0; i < NUM_HIT_SIDES; i++)
            {
                  for (j = 0; j < NUM_WEAPON_CLASS; j++)
                  {
                        psBuilding->armour[i][j] = (UWORD)((psBuilding->armour[i][j] * newBaseArmour) / prevBaseArmour);
                  }
            }
      }
}

void structureResistanceUpgrade(FUNCTION *pFunction, STRUCTURE *psBuilding)
{
      UWORD increase, prevBaseResistance, newBaseResistance;

      increase = ((STRUCTURE_UPGRADE_FUNCTION *)pFunction)->resistance;

      prevBaseResistance = (UWORD)structureResistance(psBuilding->pStructureType,
            psBuilding->player);
      newBaseResistance = (UWORD)(psBuilding->pStructureType->resistance + (psBuilding
            ->pStructureType->resistance * increase) / 100);

      if (newBaseResistance > prevBaseResistance)
      {
            psBuilding->resistance = (UWORD)((psBuilding->resistance * newBaseResistance) /
                  prevBaseResistance);
      }
}

void structureProductionUpgrade(STRUCTURE *psBuilding)
{
      FACTORY                                   *pFact;
      PRODUCTION_FUNCTION                 *pFactFunc;
      UDWORD                                    type, baseOutput, i;
    STRUCTURE_STATS             *psStat;

      switch(psBuilding->pStructureType->type)
      {
      case REF_FACTORY:
            type = FACTORY_FLAG;
            break;
      case REF_CYBORG_FACTORY:
            type = CYBORG_FLAG;
            break;
      case REF_VTOL_FACTORY:
            type = VTOL_FLAG;
            break;
      default:
            ASSERT(!"invalid or not a factory type", "structureProductionUpgrade: Invalid factory type");
            return;
      }

      //upgrade the Output
      pFact = &psBuilding->pFunctionality->factory;
      ASSERT( pFact != NULL,
            "structureProductionUpgrade: invalid Factory pointer" );

      pFactFunc = (PRODUCTION_FUNCTION *)psBuilding->pStructureType->asFuncList[0];
      ASSERT( pFactFunc != NULL,
            "structureProductionUpgrade: invalid Function pointer" );

    //current base value depends on whether there are modules attached to the structure
    baseOutput = pFactFunc->productionOutput;
    psStat = getModuleStat(psBuilding);
    if (psStat)
    {
        for (i = 0; i < pFact->capacity; i++)
        {
            baseOutput += ((PRODUCTION_FUNCTION*)psStat->asFuncList[0])->productionOutput;
        }
    }

      pFact->productionOutput = (UBYTE)(baseOutput + (pFactFunc->productionOutput *
            asProductionUpgrade[psBuilding->player][type].modifier) / 100);
}

void structureResearchUpgrade(STRUCTURE *psBuilding)
{
      RESEARCH_FACILITY             *pRes = &psBuilding->pFunctionality->researchFacility;
      RESEARCH_FUNCTION             *pResFunc;
    UDWORD                       baseOutput;
    STRUCTURE_STATS             *psStat;

      //upgrade the research points
      ASSERT(pRes != NULL, "structureResearchUpgrade: invalid Research pointer");

      pResFunc = (RESEARCH_FUNCTION *)psBuilding->pStructureType->asFuncList[0];
      ASSERT( pResFunc != NULL,
            "structureResearchUpgrade: invalid Function pointer" );

    //current base value depends on whether there are modules attached to the structure
    baseOutput = pResFunc->researchPoints;
    psStat = getModuleStat(psBuilding);
    if (psStat)
    {
        if (pRes->capacity)
        {
            baseOutput += ((RESEARCH_FUNCTION*)psStat->asFuncList[0])->researchPoints;
        }
    }
      pRes->researchPoints = baseOutput + (pResFunc->researchPoints *
            asResearchUpgrade[psBuilding->player].modifier) / 100;
}

void structureReArmUpgrade(STRUCTURE *psBuilding)
{
      REARM_PAD                           *pPad = &psBuilding->pFunctionality->rearmPad;
      REARM_FUNCTION                      *pPadFunc;

      //upgrade the reArm points
      ASSERT(pPad != NULL, "structureReArmUpgrade: invalid ReArm pointer");

      pPadFunc = (REARM_FUNCTION *)psBuilding->pStructureType->asFuncList[0];
      ASSERT( pPadFunc != NULL,
            "structureReArmUpgrade: invalid Function pointer" );

      pPad->reArmPoints = pPadFunc->reArmPoints + (pPadFunc->reArmPoints *
            asReArmUpgrade[psBuilding->player].modifier) / 100;
}

void structurePowerUpgrade(STRUCTURE *psBuilding)
{
      POWER_GEN                           *pPowerGen = &psBuilding->pFunctionality->powerGenerator;
      POWER_GEN_FUNCTION                  *pPGFunc;
    UDWORD                       baseOutput;
    STRUCTURE_STATS             *psStat;

      //upgrade the research points
      ASSERT(pPowerGen != NULL, "structurePowerUpgrade: invalid Power Gen pointer");

      pPGFunc = (POWER_GEN_FUNCTION *)psBuilding->pStructureType->asFuncList[0];
      ASSERT( pPGFunc != NULL,
            "structurePowerUpgrade: invalid Function pointer" );

    //current base value depends on whether there are modules attached to the structure
    baseOutput = pPGFunc->powerMultiplier;
    psStat = getModuleStat(psBuilding);
    if (psStat)
    {
        if (pPowerGen->capacity)
        {
            baseOutput += ((POWER_GEN_FUNCTION*)psStat->asFuncList[0])->powerOutput;
        }
    }
      pPowerGen->multiplier = baseOutput + (pPGFunc->powerMultiplier *
            asPowerUpgrade[psBuilding->player].modifier) / 100;
}

void structureRepairUpgrade(STRUCTURE *psBuilding)
{
      REPAIR_FACILITY               *pRepair = &psBuilding->pFunctionality->repairFacility;
      REPAIR_DROID_FUNCTION   *pRepairFunc;

      //upgrade the research points
      ASSERT(pRepair != NULL, "structureRepairUpgrade: invalid Repair pointer");

      pRepairFunc = (REPAIR_DROID_FUNCTION *)psBuilding->pStructureType->asFuncList[0];
      ASSERT( pRepairFunc != NULL,
            "structureRepairUpgrade: invalid Function pointer" );

      pRepair->power = pRepairFunc->repairPoints + (pRepairFunc->repairPoints *
            asRepairFacUpgrade[psBuilding->player].modifier) / 100;
}

void structureSensorUpgrade(STRUCTURE *psBuilding)
{
      //reallocate the sensor range and power since the upgrade
      if (psBuilding->pStructureType->pSensor)
      {
            psBuilding->sensorRange = (UWORD)sensorRange(psBuilding->pStructureType->
                  pSensor, psBuilding->player);
            psBuilding->sensorPower = (UWORD)sensorPower(psBuilding->pStructureType->
                  pSensor, psBuilding->player);
      }
      else
      {
            //give them the default sensor for droids if not
            psBuilding->sensorRange = (UWORD)sensorRange(asSensorStats +
                  aDefaultSensor[psBuilding->player], psBuilding->player);
            psBuilding->sensorPower = (UWORD)sensorPower(asSensorStats +
                  aDefaultSensor[psBuilding->player], psBuilding->player);
      }
}

void structureECMUpgrade(STRUCTURE *psBuilding)
{
      //reallocate the sensor range and power since the upgrade
      if (psBuilding->pStructureType->pECM)
      {
            psBuilding->ECMMod = (UWORD)ecmPower(psBuilding->pStructureType->pECM, psBuilding->player);
      }
      else
      {
            psBuilding->ECMMod = 0;
      }
}

void droidSensorUpgrade(DROID *psDroid)
{
      //reallocate the sensor range and power since the upgrade
      psDroid->sensorRange = sensorRange((asSensorStats + psDroid->asBits
            [COMP_SENSOR].nStat), psDroid->player);
      psDroid->sensorPower = sensorPower((asSensorStats + psDroid->asBits
            [COMP_SENSOR].nStat), psDroid->player);
}

void droidECMUpgrade(DROID *psDroid)
{
      //reallocate the ecm power since the upgrade
      psDroid->ECMMod = ecmPower((asECMStats + psDroid->asBits[COMP_ECM].nStat),
            psDroid->player);
}

void droidBodyUpgrade(FUNCTION *pFunction, DROID *psDroid)
{
      UDWORD      increase, prevBaseBody, newBaseBody, base;
    DROID   *psCurr;

      increase = ((DROIDBODY_UPGRADE_FUNCTION*)pFunction)->body;

      prevBaseBody = psDroid->originalBody;
      base = calcDroidBaseBody(psDroid);
      newBaseBody =  base + (base * increase) / 100;

      if (newBaseBody > prevBaseBody)
      {
            psDroid->body = (psDroid->body * newBaseBody) / prevBaseBody;
            psDroid->originalBody = newBaseBody;
      }
    //if a transporter droid then need to upgrade the contents
    if (psDroid->droidType == DROID_TRANSPORTER)
    {
        for (psCurr = psDroid->psGroup->psList; psCurr != NULL; psCurr =
            psCurr->psGrpNext)
        {
            if (psCurr != psDroid)
            {
                droidBodyUpgrade(pFunction, psCurr);
            }
        }
    }
}

//upgrade the weapon stats for the correct subclass
void weaponUpgrade(FUNCTION *pFunction, UBYTE player)
{
      WEAPON_UPGRADE_FUNCTION       *pUpgrade;

      pUpgrade = (WEAPON_UPGRADE_FUNCTION *)pFunction;

      //check upgrades increase all values!
      if (asWeaponUpgrade[player][pUpgrade->subClass].firePause < pUpgrade->firePause)
      {
        //make sure don't go less than 100%
        if (pUpgrade->firePause > 100)
        {
            pUpgrade->firePause = 100;
        }
            asWeaponUpgrade[player][pUpgrade->subClass].firePause = pUpgrade->firePause;
      }
      if (asWeaponUpgrade[player][pUpgrade->subClass].shortHit < pUpgrade->shortHit)
      {
            asWeaponUpgrade[player][pUpgrade->subClass].shortHit = pUpgrade->shortHit;
      }
      if (asWeaponUpgrade[player][pUpgrade->subClass].longHit < pUpgrade->longHit)
      {
            asWeaponUpgrade[player][pUpgrade->subClass].longHit = pUpgrade->longHit;
      }
      if (asWeaponUpgrade[player][pUpgrade->subClass].damage < pUpgrade->damage)
      {
            asWeaponUpgrade[player][pUpgrade->subClass].damage = pUpgrade->damage;
      }
      if (asWeaponUpgrade[player][pUpgrade->subClass].radiusDamage < pUpgrade->radiusDamage)
      {
            asWeaponUpgrade[player][pUpgrade->subClass].radiusDamage = pUpgrade->radiusDamage;
      }
      if (asWeaponUpgrade[player][pUpgrade->subClass].incenDamage < pUpgrade->incenDamage)
      {
            asWeaponUpgrade[player][pUpgrade->subClass].incenDamage = pUpgrade->incenDamage;
      }
      if (asWeaponUpgrade[player][pUpgrade->subClass].radiusHit < pUpgrade->radiusHit)
      {
            asWeaponUpgrade[player][pUpgrade->subClass].radiusHit = pUpgrade->radiusHit;
      }
}

//upgrade the sensor stats
void sensorUpgrade(FUNCTION *pFunction, UBYTE player)
{
      DROIDSENSOR_UPGRADE_FUNCTION        *pUpgrade;

      pUpgrade = (DROIDSENSOR_UPGRADE_FUNCTION *)pFunction;

      //check upgrades increase all values!
      if (asSensorUpgrade[player].range < pUpgrade->range)
      {
            asSensorUpgrade[player].range = pUpgrade->range;
      }
      if (asSensorUpgrade[player].power < pUpgrade->upgradePoints)
      {
            asSensorUpgrade[player].power = pUpgrade->upgradePoints;
      }
}

//upgrade the repair stats
void repairUpgrade(FUNCTION *pFunction, UBYTE player)
{
      DROIDREPAIR_UPGRADE_FUNCTION        *pUpgrade;

      pUpgrade = (DROIDREPAIR_UPGRADE_FUNCTION *)pFunction;

      //check upgrades increase all values!
      if (asRepairUpgrade[player].repairPoints < pUpgrade->upgradePoints)
      {
            asRepairUpgrade[player].repairPoints = pUpgrade->upgradePoints;
      }
}

//upgrade the repair stats
void ecmUpgrade(FUNCTION *pFunction, UBYTE player)
{
      DROIDECM_UPGRADE_FUNCTION           *pUpgrade;

      pUpgrade = (DROIDECM_UPGRADE_FUNCTION *)pFunction;

      //check upgrades increase all values!
      if (asECMUpgrade[player].power < pUpgrade->upgradePoints)
      {
            asECMUpgrade[player].power = pUpgrade->upgradePoints;
      }
}

//upgrade the repair stats
void constructorUpgrade(FUNCTION *pFunction, UBYTE player)
{
      DROIDCONSTR_UPGRADE_FUNCTION        *pUpgrade;

      pUpgrade = (DROIDCONSTR_UPGRADE_FUNCTION *)pFunction;

      //check upgrades increase all values!
      if (asConstUpgrade[player].constructPoints < pUpgrade->upgradePoints)
      {
            asConstUpgrade[player].constructPoints = pUpgrade->upgradePoints;
      }
}

//upgrade the body stats
void bodyUpgrade(FUNCTION *pFunction, UBYTE player)
{
      DROIDBODY_UPGRADE_FUNCTION          *pUpgrade;
      UBYTE                                     inc;

      pUpgrade = (DROIDBODY_UPGRADE_FUNCTION *)pFunction;

      //check upgrades increase all values!
      if (pUpgrade->droid)
      {
            if (asBodyUpgrade[player][DROID_BODY_UPGRADE].powerOutput <
                  pUpgrade->upgradePoints)
            {
                  asBodyUpgrade[player][DROID_BODY_UPGRADE].powerOutput =
                        pUpgrade->upgradePoints;
            }
            if (asBodyUpgrade[player][DROID_BODY_UPGRADE].body <
                  pUpgrade->body)
            {
                  asBodyUpgrade[player][DROID_BODY_UPGRADE].body =
                        pUpgrade->body;
            }
            for (inc=0; inc < NUM_WEAPON_CLASS; inc++)
            {
                  if (asBodyUpgrade[player][DROID_BODY_UPGRADE].armourValue[inc] <
                        pUpgrade->armourValue[inc])
                  {
                        asBodyUpgrade[player][DROID_BODY_UPGRADE].armourValue[inc] =
                              pUpgrade->armourValue[inc];
                  }
            }
      }
      if (pUpgrade->cyborg)
      {
            if (asBodyUpgrade[player][CYBORG_BODY_UPGRADE].powerOutput <
                  pUpgrade->upgradePoints)
            {
                  asBodyUpgrade[player][CYBORG_BODY_UPGRADE].powerOutput =
                        pUpgrade->upgradePoints;
            }
            if (asBodyUpgrade[player][CYBORG_BODY_UPGRADE].body <
                  pUpgrade->body)
            {
                  asBodyUpgrade[player][CYBORG_BODY_UPGRADE].body =
                        pUpgrade->body;
            }
            for (inc=0; inc < NUM_WEAPON_CLASS; inc++)
            {
                  if (asBodyUpgrade[player][CYBORG_BODY_UPGRADE].armourValue[inc] <
                        pUpgrade->armourValue[inc])
                  {
                        asBodyUpgrade[player][CYBORG_BODY_UPGRADE].armourValue[inc] =
                              pUpgrade->armourValue[inc];
                  }
            }
      }
}

//upgrade the structure stats for the correct player
void structureUpgrade(FUNCTION *pFunction, UBYTE player)
{
      STRUCTURE_UPGRADE_FUNCTION          *pUpgrade;

      pUpgrade = (STRUCTURE_UPGRADE_FUNCTION *)pFunction;

      //check upgrades increase all values!
      if (asStructureUpgrade[player].armour < pUpgrade->armour)
      {
            asStructureUpgrade[player].armour = pUpgrade->armour;
      }
      if (asStructureUpgrade[player].body < pUpgrade->body)
      {
            asStructureUpgrade[player].body = pUpgrade->body;
      }
      if (asStructureUpgrade[player].resistance < pUpgrade->resistance)
      {
            asStructureUpgrade[player].resistance = pUpgrade->resistance;
      }
}

//upgrade the wall/Defence structure stats for the correct player
void wallDefenceUpgrade(FUNCTION *pFunction, UBYTE player)
{
      WALLDEFENCE_UPGRADE_FUNCTION        *pUpgrade;

      pUpgrade = (WALLDEFENCE_UPGRADE_FUNCTION *)pFunction;

      //check upgrades increase all values!
      if (asWallDefenceUpgrade[player].armour < pUpgrade->armour)
      {
            asWallDefenceUpgrade[player].armour = pUpgrade->armour;
      }
      if (asWallDefenceUpgrade[player].body < pUpgrade->body)
      {
            asWallDefenceUpgrade[player].body = pUpgrade->body;
      }
}

/*upgrades the droids inside a Transporter uwith the appropriate upgrade function*/
void upgradeTransporterDroids(DROID *psTransporter,
                              void(*pUpgradeFunction)(DROID *psDroid))
{
    DROID   *psCurr;

    ASSERT( psTransporter->droidType == DROID_TRANSPORTER,
        "upgradeTransporterUnits: invalid unit type" );

    //loop thru' each unit in the Transporter
    for (psCurr = psTransporter->psGroup->psList; psCurr != NULL; psCurr =
        psCurr->psGrpNext)
    {
        if (psCurr != psTransporter)
        {
            //apply upgrade if not the transporter itself
            pUpgradeFunction(psCurr);
        }
    }
}

BOOL FunctionShutDown(void)
{
      UDWORD            inc;//, player;
      FUNCTION    *pFunction, **pStartList = asFunctions;

      for (inc=0; inc < numFunctions; inc++)
      {
            pFunction = *asFunctions;
            free(pFunction->pName);
            free(pFunction);
            asFunctions++;
      }
      free(pStartList);

      return true;
}

BOOL loadFunctionStats(const char *pFunctionData, UDWORD bufferSize)
{
      //array of functions pointers for each load function
      static const LoadFunction pLoadFunction[NUMFUNCTIONS] =
      {
            loadProduction,
            loadProductionUpgradeFunction,
            loadResearchFunction,
            loadResearchUpgradeFunction,
            loadPowerGenFunction,
            loadResourceFunction,
            loadRepairDroidFunction,
            loadWeaponUpgradeFunction,
            loadWallFunction,
            loadStructureUpgradeFunction,
            loadWallDefenceUpgradeFunction,
            loadPowerUpgradeFunction,
            loadRepairUpgradeFunction,
            loadDroidRepairUpgradeFunction,
            loadDroidECMUpgradeFunction,
            loadDroidBodyUpgradeFunction,
            loadDroidSensorUpgradeFunction,
            loadDroidConstUpgradeFunction,
            loadReArmFunction,
            loadReArmUpgradeFunction,
      };

      const unsigned int totalFunctions = numCR(pFunctionData, bufferSize);
      UDWORD            i, type;
      char        FunctionType[MAX_STR_LENGTH];
      FUNCTION    **pStartList;

      //allocate storage for the Function pointer array
      asFunctions = (FUNCTION**) malloc(totalFunctions*sizeof(FUNCTION*));
      if (!asFunctions)
      {
            debug( LOG_ERROR, "Out of memory" );
            abort();
            return false;
      }
      pStartList = asFunctions;
      //initialise the storage
      memset(asFunctions, 0, totalFunctions*sizeof(FUNCTION*));
      numFunctions = 0;
      //numProductionUpgrades =     numResearchUpgrades = 0;//numArmourUpgrades =
            //numRepairUpgrades = numResistanceUpgrades = numBodyUpgrades =
            //numWeaponUpgrades = 0;

      for (i=0; i < totalFunctions; i++)
      {
            //read the data into the storage - the data is delimeted using comma's
            FunctionType[0] = '\0';
            sscanf(pFunctionData, "%[^',']", FunctionType);
            type = functionType(FunctionType);
            pFunctionData += (strlen(FunctionType)+1);

            if (!(pLoadFunction[type](pFunctionData)))
            {
                  return false;
            }
            //increment the pointer to the start of the next record
            pFunctionData = strchr(pFunctionData,'\n') + 1;
      }
      //set the function list pointer to the start
      asFunctions = pStartList;

      return true;
}

Generated by  Doxygen 1.6.0   Back to index