void LogisticsVehicle::init(FitIniFile& file)
{
	componentCount = 0;
	file.seekBlock("ObjectType");
	char tmp[256];
	file.readIdString("AppearanceName", tmp, 255);
	fileName = tmp;
	file.seekBlock("General");
	file.readIdLong("DescIndex", chassisNameID);
	file.readIdFloat("CurTonnage", maxWeight);
	char tmpWeightClass[256];
	cLoadString(IDS_VEHICLE_CLASS, tmpWeightClass, 256);
	mechClass = tmpWeightClass;
	if(NO_ERROR != file.readIdLong("HouseID", houseID))
	{
		houseID = -1;
	}
	if(NO_ERROR != file.readIdLong("EncyclopediaID", encyclopediaID))
	{
		encyclopediaID = IDS_VEHICLE_DESCRIPTION_0;
	}
	file.seekBlock("VehicleDynamics");
	file.readIdFloat("MaxVelocity", speed);
	PSTR parts[5] = { "Front", "Left", "Right", "Rear", "Turret" };
	baseArmor = 0;
	uint8_t pts;
	int32_t i;
	for(i = 0; i < 5; i++)
	{
		file.seekBlock(parts[i]);
		file.readIdUChar("MaxArmorPoints", pts);
		baseArmor += pts;
		file.readIdUChar("CurInternalStructure", pts);
		baseArmor += pts;
	}
	file.seekBlock("InventoryInfo");
	file.readIdUChar("NumWeapons", pts);
	char blockName[256];
	for(i = 4; i < 4 + pts; i++)
	{
		sprintf(blockName, "Item:%ld", i);
		if(NO_ERROR == file.seekBlock(blockName))
		{
			uint8_t fitID;
			file.readIdUChar("MasterID", fitID);
			LogisticsComponent* pComponent = LogisticsData::instance->getComponent(fitID);
			if(pComponent)
			{
				components[componentCount].component = pComponent;
				components[componentCount].xCoord = 0;
				components[componentCount].yCoord = 0;
				componentCount++;
			}
		}
	}
}
예제 #2
0
long LightType::init (FilePtr objFile, unsigned long fileSize) {

	long result = 0;
	
	FitIniFile explFile;
	result = explFile.open(objFile,fileSize);
	if (result != NO_ERR)
		return(result);

	result = explFile.seekBlock("LightData");
	if (result != NO_ERR)
		return result;

	result = explFile.readIdBoolean("OneShotFlag",oneShotFlag);
	if (result != NO_ERR)
		return result;

	result = explFile.readIdFloat("AltitudeOffset",altitudeOffset);
	if (result != NO_ERR)
		return result;

	//------------------------------------------------------------------
	// Initialize the base object Type from the current file.
	result = ObjectType::init(&explFile);
	return(result);
}
예제 #3
0
//---------------------------------------------------------------------------
long SoundSystem::init (char *soundFileName)
{
	if (useSound)
	{
		FullPathFileName soundName;
		soundName.init(soundPath,soundFileName,".snd");
		
		FitIniFile soundFile;
		long result = soundFile.open(soundName);
		gosASSERT(result == NO_ERR);

		result = soundFile.seekBlock("SoundSetup");
		gosASSERT(result == NO_ERR);

		result = soundFile.readIdULong("soundHeapSize",soundHeapSize);
		gosASSERT(result == NO_ERR);
		
		result = soundFile.readIdFloat("MaxSoundDistance",maxSoundDistance);
		gosASSERT(result == NO_ERR);

		soundHeap = new UserHeap;
		gosASSERT(soundHeap != NULL);

		result = soundHeap->init(soundHeapSize,"SOUND");
		gosASSERT(result == NO_ERR);

		//-----------------------------------------------------------------------
		// Startup the Sound packet File with the sound Blocks in it.
		// This works by sound ID.  The sound ID is the packet number.
		// When ordered to play a sample, the sound system check to see if that
		// sound ID is in the cache.  If not, it is loaded.  If there is no more
		// room, any idle sounds are flushed in order of priority.
		soundDataFile = new PacketFile;
		gosASSERT(soundDataFile != NULL);
		
		FullPathFileName soundDataPath;
		soundDataPath.init(CDsoundPath,soundFileName,".pak");
		
		result = soundDataFile->open(soundDataPath);
		gosASSERT(result == NO_ERR);
		
		bettyDataFile = new PacketFile;
		gosASSERT(bettyDataFile != NULL);
		
		FullPathFileName bettyDataPath;
		bettyDataPath.init(CDsoundPath,"Betty",".pak");
		
		result = bettyDataFile->open(bettyDataPath);
		gosASSERT(result == NO_ERR);

		numBettySamples = bettyDataFile->getNumPackets();
		
		supportDataFile = new PacketFile;
		gosASSERT(supportDataFile != NULL);
		
		FullPathFileName supportDataPath;
		supportDataPath.init(CDsoundPath,"support",".pak");
		
		result = supportDataFile->open(supportDataPath);
		gosASSERT(result == NO_ERR);

		numSupportSamples = supportDataFile->getNumPackets();
 		//-----------------------------------------------------------------------
		// Load all of the sound Bite data.  Do not load actual packet unless
		// preload field is TRUE.
		result = soundFile.seekBlock("SoundBites");
		gosASSERT(result == NO_ERR);

		result = soundFile.readIdULong("numBites",numSoundBites);
		gosASSERT(result == NO_ERR);

		//-----------------------------------------------------------------------
		// Preallocate SoundBites
		sounds = (SoundBite *)soundHeap->Malloc(sizeof(SoundBite) * numSoundBites);
		gosASSERT(sounds != NULL);
		memset(sounds,0,sizeof(SoundBite) * numSoundBites);
		
		for (long i=0;i<(long)numSoundBites;i++)
		{
			char biteBlock[20];
			sprintf(biteBlock,"SoundBite%d",i);
			
			result = soundFile.seekBlock(biteBlock);
			gosASSERT(result == NO_ERR);
			
			result = soundFile.readIdULong("priority",sounds[i].priority);
			gosASSERT(result == NO_ERR);
			
			result = soundFile.readIdULong("cache",sounds[i].cacheStatus);
			gosASSERT(result == NO_ERR);
			
			result = soundFile.readIdULong("soundId",sounds[i].soundId);
			gosASSERT(result == NO_ERR);
			
			preloadSoundBite(i);		//ALWAYS Preload!!!!!!!!!!!!!

			result = soundFile.readIdFloat("volume",sounds[i].volume);
			gosASSERT(result == NO_ERR);
		}		

		//---------------------------------------------------------------
		// Load the digital Music Data Strings
		result = soundFile.seekBlock("DigitalMusic");
		gosASSERT(result == NO_ERR);
			
		result = soundFile.readIdLong("NumDMS",numDMS);
		gosASSERT(result == NO_ERR);

		result = soundFile.readIdFloat("StreamFadeDownTime",streamFadeDownTime);
		gosASSERT(result == NO_ERR);

		result = soundFile.readIdULong("StreamBitDepth",digitalStreamBitDepth);
		gosASSERT(result == NO_ERR);
			
		result = soundFile.readIdULong("StreamChannels",digitalStreamChannels);
		gosASSERT(result == NO_ERR);

		digitalMusicIds = (char **)soundHeap->Malloc(sizeof(char *) * numDMS);
		gosASSERT(digitalMusicIds != NULL);
			
		digitalMusicLoopFlags = (bool *)soundHeap->Malloc(sizeof(bool)*numDMS);
		gosASSERT(digitalMusicLoopFlags != NULL);

		digitalMusicVolume = (float *)soundHeap->Malloc(sizeof(float) * numDMS);
			
		for (i=0;i<numDMS;i++)
		{
			char digitalMSId[20];
			sprintf(digitalMSId,"DMS%d",i);
			
			char digitalMSBId[20];
			sprintf(digitalMSBId,"DMSLoop%d",i);

			char digitalMSVId[25];
			sprintf(digitalMSVId,"DMSVolume%d",i);
			
			digitalMusicIds[i] = (char *)soundHeap->Malloc(30);
			result = soundFile.readIdString(digitalMSId,digitalMusicIds[i],29);
			gosASSERT(result == NO_ERR);
			
			result = soundFile.readIdBoolean(digitalMSBId,digitalMusicLoopFlags[i]);
			gosASSERT(result == NO_ERR);

			result = soundFile.readIdFloat(digitalMSVId,digitalMusicVolume[i]);
			if (result != NO_ERR)
				digitalMusicVolume[i] = 1.0f;
		}	
		
		soundFile.close();
		
		for (i=0;i<MAX_DIGITAL_SAMPLES+4;i++)
		{
			gosAudio_AllocateChannelSliders(i,gosAudio_Volume | gosAudio_Panning);
		}
	}
	
	digitalMasterVolume = float(DigitalMasterVolume) / 256.0f;
	SFXVolume = float(sfxVolume) / 256.0f;
	musicVolume = float(MusicVolume) / 256.0f;
	radioVolume = float(RadioVolume) / 256.0f;
	bettyVolume = float(BettyVolume) / 256.0f;

	stream1Id = stream2Id = 0;

	return(NO_ERR);
}
void MissionBriefingScreen::begin()
{
	missionListBox.removeAllItems( true );

	runTime = 0;
	bClicked = 0;

	statics[VIDEO_SCREEN].setColor( 0 );

	memset( objectiveButtons, 0, sizeof ( aObject* ) * MAX_OBJECTIVES );
	// need to set up all pertinent mission info
	EString missionName = LogisticsData::instance->getCurrentMission();


	long tmpMapTextureHandle = getMissionTGA(missionName);
	statics[MAP_INDEX].setTexture( tmpMapTextureHandle );
	statics[MAP_INDEX].setUVs( 0, 127, 127, 0 );
	statics[MAP_INDEX].setColor( 0xffffffff );


	// need to get all the objectives and stuff
	FullPathFileName fitPath;
	fitPath.init(missionPath, missionName, ".fit");
	FitIniFile fitFile;
	fitFile.open( fitPath );

	// put initial divider in list box
	addItem(IDS_MN_DIVIDER, 0xff005392, -1);

	fitFile.seekBlock( "MissionSettings" );

	long result = fitFile.seekBlock( "MissionSettings" );
	Assert( result == NO_ERR, 0, "Coudln't find the mission settings block in the mission file" );

	bool bRes;
	result = fitFile.readIdBoolean( "MissionNameUseResourceString", bRes );
	Assert( result == NO_ERR, 0, "couldn't find the MissionNameUseResourceString" );
	if ( bRes )
	{
		unsigned long ulRes;
		result = fitFile.readIdULong( "MissionNameResourceStringID", ulRes );
		Assert( result == NO_ERR, 0, "couldn't find the MissionNameResourceStringID" );
		addItem(ulRes, 0xff005392, -1);
	}
	else
	{
		char missionName[256];
		fitFile.readIdString("MissionName", missionName, 255);
		addLBItem(missionName, 0xff005392, -1);

	}

	addItem(IDS_MN_DIVIDER, 0xff005392, -1);
	addItem( IDS_MN_MISSION_OBJECTIVES, 0xff005392, -1 );
	addItem(IDS_MN_DIVIDER, 0xff005392, -1);

	// put in primary objectives
	fitFile.seekBlock( "Team0Objectives" );
	unsigned long objectiveCount;
	fitFile.readIdULong( "NumObjectives", objectiveCount );
	bool bHasSecondary = 0;
	int count = 0; 

	fitFile.seekBlock( "Terrain" );
	float terrainExtentX;
	float terrainExtentY;
	fitFile.readIdFloat( "TerrainMinX", terrainExtentX );
	if ( !terrainExtentX )
		terrainExtentX = 120 * 128;
	fitFile.readIdFloat( "TerrainMinY", terrainExtentY );
	if ( !terrainExtentY )
		terrainExtentY = 120 * 128;

	CObjectives Objectives(0/*alignment*/);
	/*Note that ObjectManager is probably NULL as these objectives are read, so it's not
	cool to call any of the Status() functions of this instance of objectives (access violation
	may ensue).*/
	Objectives.Read(&fitFile);

	gosASSERT( Objectives.Count() < MAX_OBJECTIVES );

	int buttonCount = 0;

	for ( int j = 1; j < 3; j++ )
	{
		CObjectives::EIterator it = Objectives.Begin();
		buttonCount = 0;
		for ( int i = 0; i < Objectives.Count(); i++, it++ )
		{
			CObjective *pObjective = (*it);
			if ( (!pObjective->IsHiddenTrigger()) && (pObjective->IsActive()) )
			{
				
				if ( pObjective->Priority() == j )
				{
					addObjectiveButton( pObjective->MarkerX(), pObjective->MarkerY(), buttonCount,pObjective->Priority(), fabs(terrainExtentX),
									fabs(terrainExtentY), pObjective->DisplayMarker());

					if ( j == 0 )
					{
						bHasSecondary = true;
						if ( i == 0 )
							addItem( IDS_MN_DIVIDER, 0xff005392, -1 );
					}

					addLBItem( (pObjective->LocalizedDescription()).Data(), 0xffffffff, count );

					objectiveModels[count] = (pObjective->ModelName()).Data();
					modelTypes[count] = pObjective->ModelType();

					modelColors[count][0] = pObjective->ModelBaseColor();
					modelColors[count][1] = pObjective->ModelHighlightColor();
					modelColors[count][2] = pObjective->ModelHighlightColor2();
					modelScales[count] = pObjective->ModelScale();

					count++;
					buttonCount++;
				}
			}
		}
	}
	
	addItem( IDS_MN_DIVIDER, 0xff005392, -1 );

	fitFile.seekBlock( "MissionSettings" );

	char blurb[4096];
	result = fitFile.readIdString("Blurb", blurb, 4095 );

	bool tmpBool = false;
	result = fitFile.readIdBoolean("BlurbUseResourceString", tmpBool);
	if (NO_ERR == result && tmpBool )
	{
		unsigned long tmpInt = 0;
		result = fitFile.readIdULong("BlurbResourceStringID", tmpInt);
		if (NO_ERR == result)
		{
			cLoadString( tmpInt, blurb, 2047 );
		}
	}


	addLBItem( blurb, 0xff005392, -1 );

	int RP = LogisticsData::instance->getCBills();
	char text[32];
	sprintf( text, "%ld ", RP );
	textObjects[RP_INDEX].setText( text );

	// need to find a drop zone, because our designers were never convinced to place
	// 'em explicitly, we need to do it for them
	int i = 1;
	while( true )
	{
		char blockName[32];
		sprintf( blockName, "Part%ld", i );
		i++;
		if ( NO_ERR != fitFile.seekBlock( blockName ) )
			break;
		
		bool bPlayer = 0;
		fitFile.readIdBoolean( "PlayerPart", bPlayer );

		if ( bPlayer )
		{
			float fX;
			float fY;

			fitFile.readIdFloat( "PositionX", fX );
			fitFile.readIdFloat( "PositionY", fY );

			setupDropZone( fX, fY, fabs(terrainExtentX), fabs(terrainExtentY) );
		
			break;
		}
	}

	statics[BUTTON_TEXT].showGUIWindow( 0 );
	status = RUNNING;

}
예제 #5
0
//---------------------------------------------------------------------------
long GateType::init (FilePtr objFile, unsigned long fileSize)
{
	long result = 0;
	
	FitIniFile bldgFile;
	result = bldgFile.open(objFile,fileSize);
	if (result != NO_ERR)
		return(result);
	
	//------------------------------------------------------------------
	// Read in the data needed for the Gates
	result = bldgFile.seekBlock("GateData");
	if (result != NO_ERR)
		return(result);

	result = bldgFile.readIdULong("DmgLevel",dmgLevel);
	if (result != NO_ERR)
		return(result);

	bldgFile.readIdULong("BlownEffectId",blownEffectId);
	if (result != NO_ERR)
		blownEffectId = -1;
		
	bldgFile.readIdULong("NormalEffectId",normalEffectId);
	if (result != NO_ERR)
		normalEffectId = -1;
		
	bldgFile.readIdULong("DamageEffectId",damageEffectId);
	if (result != NO_ERR)
		damageEffectId = -1;

	result = bldgFile.readIdLong("BasePixelOffsetX",basePixelOffsetX);
	if (result != NO_ERR)
		basePixelOffsetX = 0;
	
	result = bldgFile.readIdLong("BasePixelOffsetY",basePixelOffsetY);
	if (result != NO_ERR)	
		basePixelOffsetY = 0;

	result = bldgFile.readIdFloat("ExplosionRadius",explRad);
	if (result != NO_ERR)
		explRad = 0.0;
		
	result = bldgFile.readIdFloat("ExplosionDamage",explDmg);
	if (result != NO_ERR)
		explDmg = 0.0;

	result = bldgFile.readIdFloat("OpenRadius",openRadius);
	if (result != NO_ERR)
		return(result);

	result = bldgFile.readIdFloat("LittleExtent",littleExtent);
	if (result != NO_ERR)
		littleExtent = 20.0;

	result = bldgFile.readIdLong ("BuildingName", gateTypeName);
	if (result != NO_ERR)
		gateTypeName = IDS_BLDOBJ_NAME;

	result = bldgFile.readIdLong( "BuildingDescription", buildingDescriptionID );
	if ( result != NO_ERR )
			buildingDescriptionID = -1;


	result = bldgFile.readIdBoolean("BlocksLineOfFire",blocksLineOfFire);
	if (result != NO_ERR)
		blocksLineOfFire = FALSE;

	//------------------------------------------------------------------
	// Initialize the base object Type from the current file.
	result = ObjectType::init(&bldgFile);
	return(result);
}
예제 #6
0
long GateType::init (FilePtr objFile, unsigned long fileSize, const char* builName)
{
	long result = 0;
	//magic 24022011 begin
	//char tmp1[16]; //magic 29112011 disabled
	//sprintf( tmp1, "%ld", objFile ); //magic 29112011 disabled
	//char tmp2[256];
	//FitIniFile MtestFile;
	//MtestFile.open("data\\vehicle_load.fit", CREATE);
	//MtestFile.writeBlock( tmp1 );
	//MtestFile.writeBlock( vehicleName );
	//MtestFile.close();
	FitIniFile bldgFile;
	FitIniFile objTypeFile;
	
	result = objTypeFile.open(objFile, fileSize);
	if (result != NO_ERR)
	{
		FullPathFileName mFullFileName;
		mFullFileName.init(objectPath, builName, ".fit");
		//FitIniFile objTypeFile;
		//MtestFile.writeBlock( mFullFileName );
		//MtestFile.close();

		long result1 = bldgFile.open(mFullFileName);
		if (result1 != NO_ERR)
		{
			Fatal(objTypeNum, " BuildingType.init1: can't open building file ");
		}
	}
	else
		bldgFile.open(objFile, fileSize);

	objTypeFile.close();

	//magic 24022011 end	
	/*FitIniFile bldgFile;
	result = bldgFile.open(objFile,fileSize);
	if (result != NO_ERR)
		return(result);*/
	
	//------------------------------------------------------------------
	// Read in the data needed for the Gates
	result = bldgFile.seekBlock("GateData");
	if (result != NO_ERR)
		return(result);

	result = bldgFile.readIdULong("DmgLevel",dmgLevel);
	if (result != NO_ERR)
		return(result);

	bldgFile.readIdULong("BlownEffectId",blownEffectId);
	if (result != NO_ERR)
		blownEffectId = -1;
		
	bldgFile.readIdULong("NormalEffectId",normalEffectId);
	if (result != NO_ERR)
		normalEffectId = -1;
		
	bldgFile.readIdULong("DamageEffectId",damageEffectId);
	if (result != NO_ERR)
		damageEffectId = -1;

	result = bldgFile.readIdLong("BasePixelOffsetX",basePixelOffsetX);
	if (result != NO_ERR)
		basePixelOffsetX = 0;
	
	result = bldgFile.readIdLong("BasePixelOffsetY",basePixelOffsetY);
	if (result != NO_ERR)	
		basePixelOffsetY = 0;

	result = bldgFile.readIdFloat("ExplosionRadius",explRad);
	if (result != NO_ERR)
		explRad = 0.0;
		
	result = bldgFile.readIdFloat("ExplosionDamage",explDmg);
	if (result != NO_ERR)
		explDmg = 0.0;

	result = bldgFile.readIdFloat("OpenRadius",openRadius);
	if (result != NO_ERR)
		return(result);

	result = bldgFile.readIdFloat("LittleExtent",littleExtent);
	if (result != NO_ERR)
		littleExtent = 20.0;

	result = bldgFile.readIdLong ("BuildingName", gateTypeName);
	if (result != NO_ERR)
		gateTypeName = IDS_BLDOBJ_NAME;

	result = bldgFile.readIdLong( "BuildingDescription", buildingDescriptionID );
	if ( result != NO_ERR )
			buildingDescriptionID = -1;


	result = bldgFile.readIdBoolean("BlocksLineOfFire",blocksLineOfFire);
	if (result != NO_ERR)
		blocksLineOfFire = FALSE;

	//magic 09092011 begin
	char s[255];
	result = bldgFile.readIdString("Name",s,254); //magic 09092011
	strcpy_s(buildingName, s);//magic 09092011

	//magic 09092011 end

	//------------------------------------------------------------------
	// Initialize the base object Type from the current file.
	result = ObjectType::init(&bldgFile);
	return(result);
}
예제 #7
0
int32_t BuildingType::init(FilePtr objFile, uint32_t fileSize)
{
	int32_t result = 0;
	FitIniFile bldgFile;
	result = bldgFile.open(objFile, fileSize);
	if(result != NO_ERROR)
		return(result);
	//-------------------------------------------------------------------
	// Since this object type handles MC1's Building and TreeBuilding
	// object types, we need to check for both. Basically, "TreeBuilding"
	// stands for animated building. Ultimately, would be nice to get
	// rid of this misleading legacy object type...
	result = bldgFile.seekBlock("TreeData");
	if(result != NO_ERROR)
	{
		result = bldgFile.seekBlock("BuildingData");
		if(result != NO_ERROR)
			return(result);
	}
	uint32_t dmgLevel;
	result = bldgFile.readIdULong("DmgLevel", dmgLevel);
	if(result != NO_ERROR)
		return(result);
	damageLevel = (float)dmgLevel;
	result = bldgFile.readIdBoolean("CanRefit", canRefit);
	if(result != NO_ERROR)
		canRefit = false;
	if(canRefit)
	{
		result = bldgFile.readIdBoolean("MechBay", mechBay);
		if(result != NO_ERROR)
			mechBay = false;
	}
	result = bldgFile.readIdFloat("ExplosionRadius", explRad);
	if(result != NO_ERROR)
		explRad = 0.0;
	result = bldgFile.readIdFloat("ExplosionDamage", explDmg);
	if(result != NO_ERROR)
		explDmg = 0.0;
	result = bldgFile.readIdFloat("Tonnage", baseTonnage);
	if(result != NO_ERROR)
		baseTonnage = 20;
	result = bldgFile.readIdLong("BattleRating", startBR);
	if(result != NO_ERROR)
		startBR = 20;
	result = bldgFile.readIdLong("NumMarines", numMarines);
	if(result != NO_ERROR)
		numMarines = 0;
	float realExtent = 0.0;
	result = bldgFile.readIdFloat("ExtentRadius", realExtent);
	if(result != NO_ERROR)
		realExtent = -1.0;
	result = bldgFile.readIdULong("ActivityEffectID", activityEffectId);
	if(result != NO_ERROR)
		activityEffectId = 0xffffffff;
	//----------------------------
	// Init sensor-related data...
	result = bldgFile.readIdLong("TeamID", teamId);
	if(result != NO_ERROR)
		teamId = -1;
	result = bldgFile.readIdFloat("SensorRange", sensorRange);
	if(result != NO_ERROR)
		sensorRange = -1.0;
	result = bldgFile.readIdLong("BuildingName", buildingTypeName);
	if(result != NO_ERROR)
		buildingTypeName = IDS_BLDOBJ_NAME;
	result = bldgFile.readIdLong("BuildingDescription", buildingDescriptionID);
	if(result != NO_ERROR)
		buildingDescriptionID = -1;
	result = bldgFile.readIdLong("BuildingDescription", buildingDescriptionID);
	if(result != NO_ERROR)
		buildingDescriptionID = -1;
	result = bldgFile.readIdLong("ResourcePoints", resourcePoints);
	if(result != NO_ERROR)
		resourcePoints = 0;
	result = bldgFile.readIdBoolean("ImpassableWhenDestroyed", marksImpassableWhenDestroyed);
	if(result != NO_ERROR)
		marksImpassableWhenDestroyed = true;
	result = bldgFile.readIdBoolean("Capturable", capturable);
	if(result != NO_ERROR)
		capturable = false;
	result = bldgFile.readIdBoolean("IsPowerSource", powerSource);
	if(result != NO_ERROR)
		powerSource = false;
	result = bldgFile.readIdFloat("LookoutTowerRange", lookoutTowerRange);
	if(result != NO_ERROR)
		lookoutTowerRange = 0.0f;
	result = bldgFile.readIdFloat("PerimeterAlarmRange", perimeterAlarmRange);
	if(result != NO_ERROR)
		perimeterAlarmRange = 0.0f;
	result = bldgFile.readIdFloat("PerimeterAlarmTimer", perimeterAlarmTimer);
	if(result != NO_ERROR)
		perimeterAlarmTimer = 0.0f;
	result = ObjectType::init(&bldgFile);
	extentRadius = realExtent;
	if(perimeterAlarmRange > 0.0f)
		extentRadius = perimeterAlarmRange;
	//--------------------------------------------------------------------------------
	// HACK!!!!! Must fix this for localization purposes--should be in the object type
	// data (can't look in the string!) --gd
	int32_t objectNameID = buildingTypeName;
	if(objectNameID < IDS_MC2_STRING_START)
		objectNameID += IDS_MC2_STRING_START;
	if(objectNameID != -1)
	{
		char s[255];
		cLoadString(objectNameID, s, 254);
	}
	for(size_t i = 0; i < 18; i++)
	{
		if(objTypeNum == WallType[i])
		{
			setSubType(BUILDING_SUBTYPE_WALL);
			break;
		}
	}
	if(objTypeNum == BRIDGE_TYPE)
		setSubType(BUILDING_SUBTYPE_LANDBRIDGE);
	return(result);
}