changeset 950:4731f23c9b89 draft

(svn r1440) -Feature: Allows more flexible airport layouts now, as the number of terminals in every group can be freely chosen -Codechange: AT_OILRIG is now 15, so that new airports can be added easily.
author celestar <celestar@openttd.org>
date Sun, 09 Jan 2005 08:49:40 +0000
parents c65878947b32
children ded2517df7c2
files aircraft_cmd.c airport.c airport.h airport_movement.h saveload.c ttd.c
diffstat 6 files changed, 200 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/aircraft_cmd.c
+++ b/aircraft_cmd.c
@@ -373,7 +373,7 @@
 		st = GetStation(v->u.air.targetairport);
 		// If an airport doesn't have terminals (so no landing space for airports),
 		// it surely doesn't have any hangars
-		if (st->xy == 0 || st->airport_tile == 0 || GetAirport(st->airport_type)->nofterminals == 0)
+		if (st->xy == 0 || st->airport_tile == 0 || GetAirport(st->airport_type)->terminals == NULL)
 					return CMD_ERROR;
 
 		if (flags & DC_EXEC) {
@@ -495,7 +495,7 @@
 
 	st = GetStation(v->current_order.station);
 	// only goto depot if the target airport has terminals (eg. it is airport)
-	if (st->xy != 0 && st->airport_tile != 0 && GetAirport(st->airport_type)->nofterminals != 0) {
+	if (st->xy != 0 && st->airport_tile != 0 && GetAirport(st->airport_type)->terminals != NULL) {
 //		printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index);
 //		v->u.air.targetairport = st->index;
 		v->current_order.type = OT_GOTO_DEPOT;
@@ -1356,7 +1356,7 @@
 		// on an airport with helipads, a helicopter will always land there
 		// and get serviced at the same time - patch setting
 		if (_patches.serviceathelipad) {
-			if (v->subtype == 0 && Airport->nofhelipads > 0) {
+			if (v->subtype == 0 && Airport->helipads != NULL) {
 				// an exerpt of ServiceAircraft, without the invisibility stuff
 				v->date_of_last_service = _date;
 				v->breakdowns_since_last_service = 0;
@@ -1518,7 +1518,7 @@
 	if (v->current_order.type == OT_GOTO_STATION) {
 		if (AirportFindFreeHelipad(v, Airport)) {return;}
 	}
-	v->u.air.state = (Airport->nofterminals != 0) ? HANGAR : HELITAKEOFF;
+	v->u.air.state = (Airport->terminals != NULL) ? HANGAR : HELITAKEOFF;
 }
 
 typedef void AircraftStateHandler(Vehicle *v, const AirportFTAClass *Airport);
@@ -1696,9 +1696,18 @@
 	return false;
 }
 
+static int GetNumTerminals(const AirportFTAClass *Airport)
+{
+	int i, num = 0;
+	
+	for (i = Airport->terminals[0]; i > 0; i--)
+		num += Airport->terminals[i];
+		
+	return num;
+}
+
 static bool AirportFindFreeTerminal(Vehicle *v, const AirportFTAClass *Airport)
 {
-	byte nofterminalspergroup, i;
 	AirportFTA *temp;
 	Station *st;
 
@@ -1712,18 +1721,29 @@
 		possible groups are checked	(in this case group 1, since that is after group 0). If that
 		fails, then attempt fails and plane waits
 	*/
-	if (Airport->nofterminalgroups > 1) {
+	if (Airport->terminals[0] > 1) {
 		st = GetStation(v->u.air.targetairport);
-		nofterminalspergroup = Airport->nofterminals / Airport->nofterminalgroups;
 		temp = Airport->layout[v->u.air.pos].next_in_chain;
 		while (temp != NULL) {
 			if (temp->heading == 255) {
 				if (!HASBITS(st->airport_flags, temp->block)) {
-					i = temp->next_position * nofterminalspergroup; // next_position denotes the group to check
-					// only that group will be checked (eg 6 terms, 2 groups)
-					// with i = 0 terms 1 - 3 and
-					// with i = 1 terms 4 - 6
-					if (FreeTerminal(v, i, i + nofterminalspergroup)) {return true;}
+					int target_group;
+					int i;
+					int group_start = 0;
+					int group_end;
+
+					//read which group do we want to go to?
+					//(the first free group)
+					target_group = temp->next_position + 1;
+
+					//at what terminal does the group start?
+					//that means, sum up all terminals of
+					//groups with lower number
+					for(i = 1; i < target_group; i++)
+						group_start += Airport->terminals[i];
+
+					group_end = group_start + Airport->terminals[target_group];
+					if (FreeTerminal(v, group_start, group_end)) {return true;}
 				}
 			}
 			else {return false;} // once the heading isn't 255, we've exhausted the possible blocks. So we cannot move
@@ -1732,29 +1752,52 @@
 	}
 
 	// if there is only 1 terminalgroup, all terminals are checked (starting from 0 to max)
-	return FreeTerminal(v, 0, Airport->nofterminals);
+	return FreeTerminal(v, 0, GetNumTerminals(Airport));
 }
 
+static int GetNumHelipads(const AirportFTAClass *Airport)
+{
+	int i, num = 0;
+	
+	for (i = Airport->helipads[0]; i > 0; i--)
+		num += Airport->helipads[i];
+		
+	return num;
+}
+
+
 static bool AirportFindFreeHelipad(Vehicle *v, const AirportFTAClass *Airport)
 {
   Station *st;
-  byte nofhelipadspergroup,  i;
   AirportFTA *temp;
 
 	// if an airport doesn't have helipads, use terminals
-	if (Airport->nofhelipads == 0) {return AirportFindFreeTerminal(v, Airport);}
+	if (Airport->helipads == NULL) {return AirportFindFreeTerminal(v, Airport);}
 
 	// if there are more helicoptergroups, pick one, just as in AirportFindFreeTerminal()
-	if (Airport->nofhelipadgroups > 1) {
+	if (Airport->helipads[0] > 1) {
 		st = GetStation(v->u.air.targetairport);
-		nofhelipadspergroup = Airport->nofhelipads / Airport->nofhelipadgroups;
 		temp = Airport->layout[v->u.air.pos].next_in_chain;
 		while (temp != NULL) {
 			if (temp->heading == 255) {
 				if (!HASBITS(st->airport_flags, temp->block)) {
-					i = temp->next_position * nofhelipadspergroup; // next position is the group to check
-					// heliports start from after TERMINALS, so MAX_TERMINALS needs to be added
-					if (FreeTerminal(v, i + MAX_TERMINALS, i + MAX_TERMINALS + nofhelipadspergroup)) {return true;}
+					int target_group;
+					int i;
+					int group_start = 0;
+					int group_end;
+
+					//read which group do we want to go to?
+					//(the first free group)
+					target_group = temp->next_position + 1;
+
+					//at what terminal does the group start?
+					//that means, sum up all terminals of
+					//groups with lower number
+					for(i = 1; i < target_group; i++)
+						group_start += Airport->helipads[i];
+
+					group_end = group_start + Airport->helipads[target_group];
+					if (FreeTerminal(v, group_start, group_end)) {return true;}
 				}
 			}
 			else {return false;} // once the heading isn't 255, we've exhausted the possible blocks. So we cannot move
@@ -1763,7 +1806,7 @@
 	}
 	// only 1 helicoptergroup, check all helipads
 	// The blocks for helipads start after the last terminal (MAX_TERMINALS)
-	else {return FreeTerminal(v, MAX_TERMINALS, Airport->nofhelipads + MAX_TERMINALS);}
+	else {return FreeTerminal(v, MAX_TERMINALS, GetNumHelipads(Airport) + MAX_TERMINALS);}
 	return false;	// it shouldn't get here anytime, but just to be sure
 }
 
@@ -1821,6 +1864,15 @@
 	}
 }
 
+void UpdateOilRig( void )
+{
+	Station *st;
+	
+	FOR_ALL_STATIONS(st) {
+		if (st->airport_type == 5) st->airport_type = AT_OILRIG;
+	}
+}
+
 // need to be called to load aircraft from old version
 void UpdateOldAircraft()
 {
--- a/airport.c
+++ b/airport.c
@@ -10,8 +10,7 @@
 AirportFTAClass *InternationalAirport;
 
 static void AirportFTAClass_Constructor(AirportFTAClass *Airport,
-																				const byte nofterminals, const byte nofterminalgroups,
-																				const byte nofhelipads,  const byte nofhelipadgroups,
+																				const byte *terminals, const byte *helipads,
 																				const byte entry_point,  const byte acc_planes,
 																				const AirportFTAbuildup *FA,
 																				const TileIndexDiffC *depots, const byte nof_depots);
@@ -26,24 +25,75 @@
 void InitializeAirports()
 {
 	// country airport
-	CountryAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
-	AirportFTAClass_Constructor(CountryAirport, 2, 1, 0, 0, 16, ALL, _airport_fta_country, _airport_depots_country, lengthof(_airport_depots_country));
+	CountryAirport = malloc(sizeof(AirportFTAClass));
+	
+	AirportFTAClass_Constructor(
+		CountryAirport, 
+		_airport_terminal_country, 
+		NULL, 
+		16, 
+		ALL, 
+		_airport_fta_country, 
+		_airport_depots_country, 
+		lengthof(_airport_depots_country)
+	);
 
 	// city airport
-	CityAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
-	AirportFTAClass_Constructor(CityAirport, 3, 1, 0, 0, 19, ALL, _airport_fta_city, _airport_depots_city, lengthof(_airport_depots_city));
+	CityAirport = malloc(sizeof(AirportFTAClass));
+	
+	AirportFTAClass_Constructor(
+		CityAirport, 
+		_airport_terminal_city, 
+		NULL, 
+		19, 
+		ALL, 
+		_airport_fta_city, 
+		_airport_depots_city, 
+		lengthof(_airport_depots_city)
+	);
 
 	// metropolitan airport
-	MetropolitanAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
-	AirportFTAClass_Constructor(MetropolitanAirport, 3, 1, 0, 0, 20, ALL, _airport_fta_metropolitan, _airport_depots_metropolitan, lengthof(_airport_depots_metropolitan));
+	MetropolitanAirport = malloc(sizeof(AirportFTAClass));
+	
+	AirportFTAClass_Constructor(
+		MetropolitanAirport, 
+		_airport_terminal_metropolitan, 
+		NULL, 
+		20, 
+		ALL, 
+		_airport_fta_metropolitan, 
+		_airport_depots_metropolitan, 
+		lengthof(_airport_depots_metropolitan)
+	);
 
 	// international airport
 	InternationalAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
-	AirportFTAClass_Constructor(InternationalAirport, 6, 2, 2, 1, 37, ALL, _airport_fta_international, _airport_depots_international, lengthof(_airport_depots_international));
+	
+	AirportFTAClass_Constructor(
+		InternationalAirport, 
+		_airport_terminal_international, 
+		_airport_helipad_international, 
+		37, 
+		ALL, 
+		_airport_fta_international, 
+		_airport_depots_international, 
+		lengthof(_airport_depots_international)
+	);
 
 	// heliport, oilrig
 	Heliport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
-	AirportFTAClass_Constructor(Heliport, 0, 0, 1, 1, 7, HELICOPTERS_ONLY, _airport_fta_heliport_oilrig, NULL, 0);
+	
+	AirportFTAClass_Constructor(
+		Heliport, 
+		NULL, 
+		_airport_helipad_heliport_oilrig, 
+		7, 
+		HELICOPTERS_ONLY, 
+		_airport_fta_heliport_oilrig, 
+		NULL, 
+		0
+	);
+	
 	Oilrig = Heliport;  // exactly the same structure for heliport/oilrig, so share state machine
 }
 
@@ -57,12 +107,46 @@
 }
 
 static void AirportFTAClass_Constructor(AirportFTAClass *Airport,
-																				const byte nofterminals, const byte nofterminalgroups,
-																				const byte nofhelipads, const byte nofhelipadgroups,
+																				const byte *terminals, const byte *helipads,
 																				const byte entry_point, const byte acc_planes,
 																				const AirportFTAbuildup *FA,
 																				const TileIndexDiffC *depots, const byte nof_depots)
 {
+	byte nofterminals, nofhelipads;
+	byte nofterminalgroups = 0;
+	byte nofhelipadgroups = 0;
+	const byte * curr;
+	int i;
+	nofterminals = nofhelipads = 0;
+	
+	//now we read the number of terminals we have
+	if (terminals != NULL) {
+		i = terminals[0];
+		nofterminalgroups = i;
+		curr = terminals;
+		while (i-- > 0) {
+			curr++;
+			assert(*curr != 0);	//we don't want to have an empty group
+			nofterminals += *curr;
+		}
+	
+	}
+	Airport->terminals = terminals;
+
+	//read helipads	
+	if (helipads != NULL) {
+		i = helipads[0];
+		nofhelipadgroups = i;
+		curr = helipads;
+		while (i-- > 0) {
+			curr++;
+			assert(*curr != 0); //no empty groups please
+			nofhelipads += *curr;
+		}
+	
+	}
+	Airport->helipads = helipads;
+
 	// if there are more terminals than 6, internal variables have to be changed, so don't allow that
 	// same goes for helipads
 	if (nofterminals > MAX_TERMINALS) { printf("Currently only maximum of %2d terminals are supported (you wanted %2d)\n", MAX_TERMINALS, nofterminals);}
@@ -70,23 +154,15 @@
 	// terminals/helipads are divided into groups. Groups are computed by dividing the number
 	// of terminals by the number of groups. Half in half. If #terminals is uneven, first group
 	// will get the less # of terminals
-	if (nofterminalgroups > nofterminals) { printf("# of terminalgroups (%2d) must be less or equal to terminals (%2d)", nofterminals, nofterminalgroups);}
-	if (nofhelipadgroups > nofhelipads) { printf("# of helipadgroups (%2d) must be less or equal to helipads (%2d)", nofhelipads, nofhelipadgroups);}
 
 	assert(nofterminals <= MAX_TERMINALS);
 	assert(nofhelipads <= MAX_HELIPADS);
-	assert(nofterminalgroups <= nofterminals);
-	assert(nofhelipadgroups <= nofhelipads);
 
 	Airport->nofelements = AirportGetNofElements(FA);
 	// check
 	if (entry_point >= Airport->nofelements) {printf("Entry point (%2d) must be within the airport positions (which is max %2d)\n", entry_point, Airport->nofelements);}
 	assert(entry_point < Airport->nofelements);
 
-	Airport->nofterminals = nofterminals;
-	Airport->nofterminalgroups = nofterminalgroups;
-	Airport->nofhelipads = nofhelipads;
-	Airport->nofhelipadgroups = nofhelipadgroups;
 	Airport->acc_planes = acc_planes;
 	Airport->entry_point = entry_point;
 	Airport->airport_depots = depots;
@@ -95,8 +171,8 @@
 
 	// build the state machine
 	AirportBuildAutomata(Airport, FA);
-		DEBUG(misc, 1) ("#Elements %2d; #Terminals %2d in %d group(s); #Helipads %2d in %d group(s)", Airport->nofelements,
-				  Airport->nofterminals, Airport->nofterminalgroups, Airport->nofhelipads, Airport->nofhelipadgroups);
+		DEBUG(misc, 1) ("#Elements %2d; #Terminals %2d in %d group(s); #Helipads %2d in %d group(s); Entry Point %d", Airport->nofelements,
+				  nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups, Airport->entry_point);
 
 
 	{
--- a/airport.h
+++ b/airport.h
@@ -13,7 +13,7 @@
 	AT_HELIPORT = 2,
 	AT_METROPOLITAN = 3,
 	AT_INTERNATIONAL = 4,
-	AT_OILRIG = 5
+	AT_OILRIG = 15
 };
 
 // do not change unless you change v->subtype too. This aligns perfectly with its current setting
@@ -26,10 +26,8 @@
 // Finite sTate mAchine --> FTA
 typedef struct AirportFTAClass {
 	byte nofelements;							// number of positions the airport consists of
-	byte nofterminals;						// number of terminals this airport has
-	byte nofterminalgroups;				// terminals belong to so many groups (MAX is the nofterminals)
-	byte nofhelipads;							// number of helipads this airport has
-	byte nofhelipadgroups;				// helipads belong to so many groups (MAX is the nofhelipads)
+	const byte *terminals;
+	const byte *helipads;
 	byte entry_point;							// when an airplane arrives at this airport, enter it at position entry_point
 	byte acc_planes;							// accept airplanes or helicopters or both
 	const TileIndexDiffC *airport_depots;	// gives the position of the depots on the airports
--- a/airport_movement.h
+++ b/airport_movement.h
@@ -264,6 +264,7 @@
 // first element of depots array tells us how many depots there are (to know size of array)
 // this may be changed later when airports are moved to external file
 static const TileIndexDiffC _airport_depots_country[] = {{3, 0}};
+static const byte _airport_terminal_country[] = {1, 2};
 static const AirportFTAbuildup _airport_fta_country[] = {
 	{ 0,HANGAR,NOTHING_block,1},
 	{ 1,255,AIRPORT_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM1,TERM1_block,2}, {1,TERM2,0,4}, {1,HELITAKEOFF,0,19}, {1,0,0,6},
@@ -294,6 +295,7 @@
 };
 
 static const TileIndexDiffC _airport_depots_city[] = {{5, 0}};
+static const byte _airport_terminal_city[] = {1, 3};
 static const AirportFTAbuildup _airport_fta_city[] = {
 	{ 0,HANGAR,NOTHING_block,1}, {0,TAKEOFF,OUT_WAY_block,1}, {0,0,0,1},
 	{ 1,255,TAXIWAY_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM2,0,6}, {1,TERM3,0,6}, {1,0,0,7}, // for all else, go to 7
@@ -328,6 +330,7 @@
 };
 
 static const TileIndexDiffC _airport_depots_metropolitan[] = {{5, 0}};
+static const byte _airport_terminal_metropolitan[] = {1, 3};
 static const AirportFTAbuildup _airport_fta_metropolitan[] = {
 	{ 0,HANGAR,NOTHING_block,1},
 	{ 1,255,TAXIWAY_BUSY_block,0}, {1,HANGAR,0,0}, {1,TERM2,0,6}, {1,TERM3,0,6}, {1,0,0,7}, // for all else, go to 7
@@ -364,6 +367,8 @@
 };
 
 static const TileIndexDiffC _airport_depots_international[] = {{0, 3}, {6, 1}};
+static const byte _airport_terminal_international[] = {2, 3, 3};
+static const byte _airport_helipad_international[] = {1, 2};
 static const AirportFTAbuildup _airport_fta_international[] = {
 	{ 0,HANGAR,NOTHING_block,2}, {0,255,TERM_GROUP1_block,0}, {0,255,TERM_GROUP2_ENTER1_block,1}, {0,HELITAKEOFF,HELIPAD1_block,2}, {0,0,0,2},
 	{ 1,HANGAR,NOTHING_block,3}, {1,255,HANGAR2_AREA_block,1}, {1,HELITAKEOFF,HELIPAD2_block,3}, {1,0,0,3},
@@ -426,6 +431,7 @@
 };
 
 // heliports, oilrigs don't have depots
+static const byte _airport_helipad_heliport_oilrig[] = {1, 1};
 static const AirportFTAbuildup _airport_fta_heliport_oilrig[] = {
 	{0,HELIPAD1,HELIPAD1_block,1},
 	{1,HELITAKEOFF,NOTHING_block,0}, // takeoff
@@ -440,12 +446,22 @@
 	{MAX_ELEMENTS,0,0,0} // end marker. DO NOT REMOVE
 };
 
-static const AirportMovingData * const _airport_moving_datas[6] = {
+static const AirportMovingData * const _airport_moving_datas[] = {
 	_airport_moving_data_country,				// Country Airfield (small) 4x3
 	_airport_moving_data_town,					// City Airport (large) 6x6
 	_airport_moving_data_heliport,			// Heliport
 	_airport_moving_data_metropolitan,	// Metropolitain Airport (large) - 2 runways
 	_airport_moving_data_international,	// International Airport (xlarge) - 2 runways
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
 	_airport_moving_data_oilrig					// Oilrig
 };
 
--- a/saveload.c
+++ b/saveload.c
@@ -8,7 +8,7 @@
 
 enum {
 	SAVEGAME_MAJOR_VERSION = 5,
-	SAVEGAME_MINOR_VERSION = 0,
+	SAVEGAME_MINOR_VERSION = 1,
 
 	SAVEGAME_LOADABLE_VERSION = (SAVEGAME_MAJOR_VERSION << 8) + SAVEGAME_MINOR_VERSION
 };
--- a/ttd.c
+++ b/ttd.c
@@ -1250,13 +1250,14 @@
 	memset(_map_type_and_height + MapMaxY() * MapSizeX(), MP_VOID << 4, MapSizeX());
 }
 
-extern void UpdateOldAircraft();
+extern void UpdateOldAircraft( void );
+extern void UpdateOilRig( void );
 
 bool AfterLoadGame(uint version)
 {
 	Window *w;
 	ViewPort *vp;
-
+	
 	// in version 2.1 of the savegame, town owner was unified.
 	if (version <= 0x200) {
 		ConvertTownOwner();
@@ -1354,6 +1355,11 @@
 	DoZoomInOutWindow(ZOOM_NONE, w); // update button status
 	MarkWholeScreenDirty();
 
+	//In 5.1, Oilrigs have been moved (again)
+	if (version <= 0x500) {
+		UpdateOilRig();
+	}
+
 	return true;
 }