(svn r3167) - NewGRF: Start moving custom station code to separate files.
Rewrite handling of station classes.
          Allow for more than 8 station tile layouts.
          Start of code to unload custom stations.
			
			
This commit is contained in:
		
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							@@ -659,6 +659,7 @@ C_SOURCES += sprite.c
 | 
			
		||||
C_SOURCES += spritecache.c
 | 
			
		||||
C_SOURCES += station_cmd.c
 | 
			
		||||
C_SOURCES += station_gui.c
 | 
			
		||||
C_SOURCES += station_newgrf.c
 | 
			
		||||
C_SOURCES += string.c
 | 
			
		||||
C_SOURCES += strings.c
 | 
			
		||||
C_SOURCES += subsidy_gui.c
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										73
									
								
								newgrf.c
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								newgrf.c
									
									
									
									
									
								
							@@ -800,22 +800,7 @@ static bool StationChangeInfo(uint stid, int numinfo, int prop, byte **bufp, int
 | 
			
		||||
				classid |= *(buf++) << 8;
 | 
			
		||||
				classid |= *(buf++);
 | 
			
		||||
 | 
			
		||||
				switch (classid) {
 | 
			
		||||
					case 'DFLT':
 | 
			
		||||
						stat->sclass = STAT_CLASS_DFLT;
 | 
			
		||||
						break;
 | 
			
		||||
					case 'WAYP':
 | 
			
		||||
						stat->sclass = STAT_CLASS_WAYP;
 | 
			
		||||
						break;
 | 
			
		||||
					default:
 | 
			
		||||
						/* TODO: No support for custom
 | 
			
		||||
						 * classes for now, so stuff
 | 
			
		||||
						 * everything to the single
 | 
			
		||||
						 * default one. --pasky */
 | 
			
		||||
						stat->sclass = STAT_CLASS_DFLT;
 | 
			
		||||
						//stat->sclass = STAT_CLASS_CUSTOM;
 | 
			
		||||
						break;
 | 
			
		||||
				}
 | 
			
		||||
				stat->sclass = AllocateStationClass(classid);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
@@ -825,24 +810,28 @@ static bool StationChangeInfo(uint stid, int numinfo, int prop, byte **bufp, int
 | 
			
		||||
				StationSpec *stat = &_cur_grffile->stations[stid + i];
 | 
			
		||||
				int t;
 | 
			
		||||
 | 
			
		||||
				stat->tiles = grf_load_byte(&buf);
 | 
			
		||||
				stat->tiles = grf_load_extended(&buf);
 | 
			
		||||
				stat->renderdata = calloc(stat->tiles, sizeof(*stat->renderdata));
 | 
			
		||||
				for (t = 0; t < stat->tiles; t++) {
 | 
			
		||||
					DrawTileSprites *dts = &stat->renderdata[t];
 | 
			
		||||
					int seq_count = 0;
 | 
			
		||||
					PalSpriteID ground_sprite;
 | 
			
		||||
 | 
			
		||||
					if (t >= 8) {
 | 
			
		||||
						grfmsg(GMS_WARN, "StationChangeInfo: Sprite %d>=8, skipping.", t);
 | 
			
		||||
						grf_load_dword(&buf); // at least something
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					dts->ground_sprite = grf_load_dword(&buf);
 | 
			
		||||
					if (!dts->ground_sprite) {
 | 
			
		||||
					ground_sprite = grf_load_dword(&buf);
 | 
			
		||||
					if (ground_sprite == 0) {
 | 
			
		||||
						static const DrawTileSeqStruct empty = {0x80, 0, 0, 0, 0, 0, 0};
 | 
			
		||||
						dts->seq = ∅
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (HASBIT(ground_sprite, 31)) {
 | 
			
		||||
						// Bit 31 indicates that we should use a custom sprite.
 | 
			
		||||
						dts->ground_sprite = GB(ground_sprite, 0, 15) - 0x42D;
 | 
			
		||||
						dts->ground_sprite += _cur_grffile->first_spriteset;
 | 
			
		||||
					} else {
 | 
			
		||||
						dts->ground_sprite = ground_sprite;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					dts->seq = NULL;
 | 
			
		||||
					while (buf < *bufp + len) {
 | 
			
		||||
						DrawTileSeqStruct *dtss;
 | 
			
		||||
@@ -873,6 +862,7 @@ static bool StationChangeInfo(uint stid, int numinfo, int prop, byte **bufp, int
 | 
			
		||||
				int t;
 | 
			
		||||
 | 
			
		||||
				stat->tiles = srcstat->tiles;
 | 
			
		||||
				stat->renderdata = calloc(stat->tiles, sizeof(*stat->renderdata));
 | 
			
		||||
				for (t = 0; t < stat->tiles; t++) {
 | 
			
		||||
					DrawTileSprites *dts = &stat->renderdata[t];
 | 
			
		||||
					const DrawTileSprites *sdts = &srcstat->renderdata[t];
 | 
			
		||||
@@ -1548,6 +1538,9 @@ static void NewSpriteGroup(byte *buf, int len)
 | 
			
		||||
	loaded_ptr = buf;
 | 
			
		||||
	loading_ptr = buf + 2 * numloaded;
 | 
			
		||||
 | 
			
		||||
	if (_cur_grffile->first_spriteset == 0)
 | 
			
		||||
		_cur_grffile->first_spriteset = _cur_grffile->spriteset_start;
 | 
			
		||||
 | 
			
		||||
	if (numloaded > 16) {
 | 
			
		||||
		grfmsg(GMS_WARN, "NewSpriteGroup: More than 16 sprites in group %x, skipping the rest.", setid);
 | 
			
		||||
		numloaded = 16;
 | 
			
		||||
@@ -1688,8 +1681,8 @@ static void NewVehicle_SpriteGroupMapping(byte *buf, int len)
 | 
			
		||||
				stat->spritegroup[0] = _cur_grffile->spritegroups[groupid];
 | 
			
		||||
				stat->spritegroup[0]->ref_count++;
 | 
			
		||||
				stat->grfid = _cur_grffile->grfid;
 | 
			
		||||
				SetCustomStation(stid, stat);
 | 
			
		||||
				stat->sclass = STAT_CLASS_NONE;
 | 
			
		||||
				stat->localidx = stid;
 | 
			
		||||
				SetCustomStation(stat);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
@@ -2396,6 +2389,28 @@ static void ReleaseSpriteGroups(GRFFile *file)
 | 
			
		||||
	file->spritegroups_count = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ResetCustomStations(void)
 | 
			
		||||
{
 | 
			
		||||
	GRFFile *file;
 | 
			
		||||
	int i;
 | 
			
		||||
	CargoID c;
 | 
			
		||||
 | 
			
		||||
	for (file = _first_grffile; file != NULL; file = file->next) {
 | 
			
		||||
		for (i = 0; i < 256; i++) {
 | 
			
		||||
			if (file->stations[i].grfid != file->grfid)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			// TODO: Release renderdata, platforms and layouts
 | 
			
		||||
 | 
			
		||||
			// Release this stations sprite groups.
 | 
			
		||||
			for (c = 0; c < NUM_GLOBAL_CID; c++) {
 | 
			
		||||
				if (file->stations[i].spritegroup[c] != NULL)
 | 
			
		||||
					UnloadSpriteGroup(&file->stations[i].spritegroup[c]);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reset all NewGRF loaded data
 | 
			
		||||
 * TODO
 | 
			
		||||
@@ -2433,6 +2448,10 @@ static void ResetNewGRFData(void)
 | 
			
		||||
 | 
			
		||||
	// Reset price base data
 | 
			
		||||
	ResetPriceBaseMultipliers();
 | 
			
		||||
 | 
			
		||||
	// Reset station classes
 | 
			
		||||
	ResetStationClasses();
 | 
			
		||||
	ResetCustomStations();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void InitNewGRFFile(const char* filename, int sprite_offset)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								newgrf.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								newgrf.h
									
									
									
									
									
								
							@@ -12,6 +12,7 @@ struct GRFFile {
 | 
			
		||||
	uint32 grfid;
 | 
			
		||||
	uint16 flags;
 | 
			
		||||
	uint16 sprite_offset;
 | 
			
		||||
	SpriteID first_spriteset; ///< Holds the first spriteset's sprite offset.
 | 
			
		||||
	GRFFile *next;
 | 
			
		||||
 | 
			
		||||
	/* A sprite group contains all sprites of a given vehicle (or multiple
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								rail_gui.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								rail_gui.c
									
									
									
									
									
								
							@@ -127,7 +127,7 @@ static void PlaceRail_Depot(TileIndex tile)
 | 
			
		||||
static void PlaceRail_Waypoint(TileIndex tile)
 | 
			
		||||
{
 | 
			
		||||
	if (!_remove_button_clicked) {
 | 
			
		||||
		DoCommandP(tile, (_waypoint_count > 0) ? (0x100 + _cur_waypoint_type) : 0, 0, CcPlaySound1E, CMD_BUILD_TRAIN_WAYPOINT | CMD_MSG(STR_CANT_BUILD_TRAIN_WAYPOINT));
 | 
			
		||||
		DoCommandP(tile, _cur_waypoint_type, 0, CcPlaySound1E, CMD_BUILD_TRAIN_WAYPOINT | CMD_MSG(STR_CANT_BUILD_TRAIN_WAYPOINT));
 | 
			
		||||
	} else {
 | 
			
		||||
		DoCommandP(tile, 0, 0, CcPlaySound1E, CMD_REMOVE_TRAIN_WAYPOINT | CMD_MSG(STR_CANT_REMOVE_TRAIN_WAYPOINT));
 | 
			
		||||
	}
 | 
			
		||||
@@ -257,9 +257,9 @@ static void BuildRailClick_Depot(Window *w)
 | 
			
		||||
 | 
			
		||||
static void BuildRailClick_Waypoint(Window *w)
 | 
			
		||||
{
 | 
			
		||||
	_waypoint_count = GetCustomStationsCount(STAT_CLASS_WAYP);
 | 
			
		||||
	_waypoint_count = GetNumCustomStations(STAT_CLASS_WAYP);
 | 
			
		||||
	if (HandlePlacePushButton(w, 11, SPR_CURSOR_WAYPOINT, 1, PlaceRail_Waypoint)
 | 
			
		||||
	    && _waypoint_count > 0)
 | 
			
		||||
			&& _waypoint_count > 1)
 | 
			
		||||
		ShowBuildWaypointPicker();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -829,14 +829,14 @@ static void BuildWaypointWndProc(Window *w, WindowEvent *e)
 | 
			
		||||
{
 | 
			
		||||
	switch (e->event) {
 | 
			
		||||
	case WE_PAINT: {
 | 
			
		||||
		int i;
 | 
			
		||||
		w->click_state = (1 << 3) << (_cur_waypoint_type - w->hscroll.pos);
 | 
			
		||||
		DrawWindowWidgets(w);
 | 
			
		||||
 | 
			
		||||
		if(w->hscroll.pos + 0 <= _waypoint_count) DrawWaypointSprite(2,   25, w->hscroll.pos + 0, _cur_railtype);
 | 
			
		||||
		if(w->hscroll.pos + 1 <= _waypoint_count) DrawWaypointSprite(70,  25, w->hscroll.pos + 1, _cur_railtype);
 | 
			
		||||
		if(w->hscroll.pos + 2 <= _waypoint_count) DrawWaypointSprite(138, 25, w->hscroll.pos + 2, _cur_railtype);
 | 
			
		||||
		if(w->hscroll.pos + 3 <= _waypoint_count) DrawWaypointSprite(206, 25, w->hscroll.pos + 3, _cur_railtype);
 | 
			
		||||
		if(w->hscroll.pos + 4 <= _waypoint_count) DrawWaypointSprite(274, 25, w->hscroll.pos + 4, _cur_railtype);
 | 
			
		||||
		for (i = 0; i < 5; i++)
 | 
			
		||||
			if(w->hscroll.pos + i < _waypoint_count)
 | 
			
		||||
				DrawWaypointSprite(2 + i * 68, 25, w->hscroll.pos + i, _cur_railtype);
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	case WE_CLICK: {
 | 
			
		||||
@@ -889,7 +889,7 @@ static void ShowBuildWaypointPicker(void)
 | 
			
		||||
{
 | 
			
		||||
	Window *w = AllocateWindowDesc(&_build_waypoint_desc);
 | 
			
		||||
	w->hscroll.cap = 5;
 | 
			
		||||
	w->hscroll.count = _waypoint_count + 1;
 | 
			
		||||
	w->hscroll.count = _waypoint_count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										74
									
								
								station.h
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								station.h
									
									
									
									
									
								
							@@ -8,6 +8,7 @@
 | 
			
		||||
#include "sprite.h"
 | 
			
		||||
#include "tile.h"
 | 
			
		||||
#include "vehicle.h"
 | 
			
		||||
#include "station_newgrf.h"
 | 
			
		||||
 | 
			
		||||
typedef struct GoodsEntry {
 | 
			
		||||
	uint16 waiting_acceptance;
 | 
			
		||||
@@ -195,83 +196,10 @@ uint GetStationPlatforms(const Station *st, TileIndex tile);
 | 
			
		||||
 | 
			
		||||
void StationPickerDrawSprite(int x, int y, RailType railtype, int image);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Station layout for given dimensions - it is a two-dimensional array
 | 
			
		||||
 * where index is computed as (x * platforms) + platform. */
 | 
			
		||||
typedef byte *StationLayout;
 | 
			
		||||
 | 
			
		||||
typedef enum StationClass {
 | 
			
		||||
	STAT_CLASS_NONE, // unused station slot or so
 | 
			
		||||
	STAT_CLASS_DFLT, // default station class
 | 
			
		||||
	STAT_CLASS_WAYP, // waypoints
 | 
			
		||||
 | 
			
		||||
	/* TODO: When we actually support custom classes, they are
 | 
			
		||||
	 * going to be allocated dynamically (with some classid->sclass
 | 
			
		||||
	 * mapping, there's a TTDPatch limit on 16 custom classes in
 | 
			
		||||
	 * the whole game at the same time) with base at
 | 
			
		||||
	 * STAT_CLASS_CUSTOM. --pasky */
 | 
			
		||||
	STAT_CLASS_CUSTOM, // some custom class
 | 
			
		||||
} StationClass;
 | 
			
		||||
 | 
			
		||||
typedef struct StationSpec {
 | 
			
		||||
	uint32 grfid;
 | 
			
		||||
	int localidx; // per-GRFFile station index + 1; SetCustomStation() takes care of this
 | 
			
		||||
 | 
			
		||||
	StationClass sclass;
 | 
			
		||||
 | 
			
		||||
	/* Bitmask of platform numbers/lengths available for the station.  Bits
 | 
			
		||||
	 * 0..6 correspond to 1..7, while bit 7 corresponds to >7 platforms or
 | 
			
		||||
	 * lenght. */
 | 
			
		||||
	byte allowed_platforms;
 | 
			
		||||
	byte allowed_lengths;
 | 
			
		||||
 | 
			
		||||
	/* Custom sprites */
 | 
			
		||||
	byte tiles;
 | 
			
		||||
	/* 00 = plain platform
 | 
			
		||||
	 * 02 = platform with building
 | 
			
		||||
	 * 04 = platform with roof, left side
 | 
			
		||||
	 * 06 = platform with roof, right side
 | 
			
		||||
	 *
 | 
			
		||||
	 * These numbers are used for stations in NE-SW direction, or these
 | 
			
		||||
	 * numbers plus one for stations in the NW-SE direction.  */
 | 
			
		||||
	DrawTileSprites renderdata[8];
 | 
			
		||||
 | 
			
		||||
	/* Custom layouts */
 | 
			
		||||
	/* The layout array is organized like [lenghts][platforms], both being
 | 
			
		||||
	 * dynamic arrays, the field itself is length*platforms array containing
 | 
			
		||||
	 * indexes to @renderdata (only even numbers allowed) for the given
 | 
			
		||||
	 * station tile. */
 | 
			
		||||
	/* @lengths is length of the @platforms and @layouts arrays, that is
 | 
			
		||||
	 * number of maximal length for which the layout is defined (since
 | 
			
		||||
	 * arrays are indexed from 0, the length itself is at [length - 1]). */
 | 
			
		||||
	byte lengths;
 | 
			
		||||
	/* @platforms is array of number of platforms defined for each length.
 | 
			
		||||
	 * Zero means no platforms defined. */
 | 
			
		||||
	byte *platforms;
 | 
			
		||||
	/* @layout is @layouts-sized array of @platforms-sized arrays,
 | 
			
		||||
	 * containing pointers to length*platforms-sized arrays or NULL if
 | 
			
		||||
	 * default OTTD station layout should be used for stations of these
 | 
			
		||||
	 * dimensions. */
 | 
			
		||||
	StationLayout **layouts;
 | 
			
		||||
 | 
			
		||||
	/* Sprite offsets for renderdata->seq->image. spritegroup[0] is default
 | 
			
		||||
	 * whilst spritegroup[1] is "GC_PURCHASE". */
 | 
			
		||||
	SpriteGroup *spritegroup[2];
 | 
			
		||||
} StationSpec;
 | 
			
		||||
 | 
			
		||||
/* Here, @stid is local per-GRFFile station index. If spec->localidx is not yet
 | 
			
		||||
 * set, it gets new dynamically allocated global index and spec->localidx is
 | 
			
		||||
 * set to @stid, otherwise we take it as that we are replacing it and try to
 | 
			
		||||
 * search for it first (that isn't much fast but we do it only very seldom). */
 | 
			
		||||
void SetCustomStation(byte stid, StationSpec *spec);
 | 
			
		||||
/* Here, @stid is global station index (in continous range 0..GetCustomStationsCount())
 | 
			
		||||
 * (lookup is therefore very fast as we do this very frequently). */
 | 
			
		||||
StationSpec *GetCustomStation(StationClass sclass, byte stid);
 | 
			
		||||
/* Get sprite offset for a given custom station and station structure (may be
 | 
			
		||||
 * NULL if ctype is set - that means we are in a build dialog). The station
 | 
			
		||||
 * structure is used for variational sprite groups. */
 | 
			
		||||
uint32 GetCustomStationRelocation(const StationSpec *spec, const Station *st, byte ctype);
 | 
			
		||||
int GetCustomStationsCount(StationClass sclass);
 | 
			
		||||
 | 
			
		||||
RoadStop * GetRoadStopByTile(TileIndex tile, RoadStopType type);
 | 
			
		||||
static inline int GetRoadStopType(TileIndex tile)
 | 
			
		||||
 
 | 
			
		||||
@@ -1199,60 +1199,6 @@ uint GetStationPlatforms(const Station *st, TileIndex tile)
 | 
			
		||||
	return len - 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* TODO: Custom classes! */
 | 
			
		||||
/* Indexed by class, just STAT_CLASS_DFLT and STAT_CLASS_WAYP supported. */
 | 
			
		||||
static int _statspec_highest_id[2] = {-1, -1};
 | 
			
		||||
static StationSpec _station_spec[2][256];
 | 
			
		||||
 | 
			
		||||
void SetCustomStation(byte local_stid, StationSpec *spec)
 | 
			
		||||
{
 | 
			
		||||
	StationClass sclass;
 | 
			
		||||
	int stid = -1;
 | 
			
		||||
 | 
			
		||||
	assert(spec->sclass == STAT_CLASS_DFLT || spec->sclass == STAT_CLASS_WAYP);
 | 
			
		||||
	sclass = spec->sclass - 1;
 | 
			
		||||
 | 
			
		||||
	if (spec->localidx != 0) {
 | 
			
		||||
		/* Already allocated, try to resolve to global stid */
 | 
			
		||||
		int i;
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i <= _statspec_highest_id[sclass]; i++) {
 | 
			
		||||
			if (_station_spec[sclass][i].grfid == spec->grfid &&
 | 
			
		||||
					_station_spec[sclass][i].localidx == local_stid + 1) {
 | 
			
		||||
				stid = i;
 | 
			
		||||
				/* FIXME: Release original SpriteGroup to
 | 
			
		||||
				 * prevent leaks. But first we need to
 | 
			
		||||
				 * refcount the SpriteGroup. --pasky */
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (stid == -1) {
 | 
			
		||||
		/* Allocate new one. */
 | 
			
		||||
		if (_statspec_highest_id[sclass] >= 255) {
 | 
			
		||||
			error("Too many custom stations allocated.");
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		stid = ++_statspec_highest_id[sclass];
 | 
			
		||||
		spec->localidx = local_stid + 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//debug("Registering station #%d of class %d", stid, sclass);
 | 
			
		||||
	memcpy(&_station_spec[sclass][stid], spec, sizeof(*spec));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
StationSpec *GetCustomStation(StationClass sclass, byte stid)
 | 
			
		||||
{
 | 
			
		||||
	assert(sclass == STAT_CLASS_DFLT || sclass == STAT_CLASS_WAYP);
 | 
			
		||||
	sclass--;
 | 
			
		||||
	//debug("Asking for station #%d of class %d", stid, sclass);
 | 
			
		||||
	if (stid > _statspec_highest_id[sclass])
 | 
			
		||||
		return NULL;
 | 
			
		||||
	return &_station_spec[sclass][stid];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const RealSpriteGroup *ResolveStationSpriteGroup(const SpriteGroup *spg, const Station *st)
 | 
			
		||||
{
 | 
			
		||||
	switch (spg->type) {
 | 
			
		||||
@@ -1351,14 +1297,6 @@ uint32 GetCustomStationRelocation(const StationSpec *spec, const Station *st, by
 | 
			
		||||
	return SPR_RAIL_PLATFORM_Y_FRONT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int GetCustomStationsCount(StationClass sclass)
 | 
			
		||||
{
 | 
			
		||||
	assert(sclass == STAT_CLASS_DFLT || sclass == STAT_CLASS_WAYP);
 | 
			
		||||
	sclass--;
 | 
			
		||||
	return _statspec_highest_id[sclass] + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int32 RemoveRailroadStation(Station *st, TileIndex tile, uint32 flags)
 | 
			
		||||
{
 | 
			
		||||
	int w,h;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										115
									
								
								station_newgrf.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								station_newgrf.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
			
		||||
/* $Id$ */
 | 
			
		||||
 | 
			
		||||
/** @file station_newgrf.c Functions for dealing with station classes and custom stations. */
 | 
			
		||||
 | 
			
		||||
#include "stdafx.h"
 | 
			
		||||
#include "openttd.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "sprite.h"
 | 
			
		||||
#include "station_newgrf.h"
 | 
			
		||||
 | 
			
		||||
static StationClass station_classes[STAT_CLASS_MAX];
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reset station classes to their default state.
 | 
			
		||||
 * This includes initialising the Default and Waypoint classes with an empty
 | 
			
		||||
 * entry, for standard stations and waypoints.
 | 
			
		||||
 */
 | 
			
		||||
void ResetStationClasses(void)
 | 
			
		||||
{
 | 
			
		||||
	StationClassID i;
 | 
			
		||||
	for (i = 0; i < STAT_CLASS_MAX; i++) {
 | 
			
		||||
		station_classes[i].id = 0;
 | 
			
		||||
 | 
			
		||||
		free(station_classes[i].name);
 | 
			
		||||
		station_classes[i].name = NULL;
 | 
			
		||||
 | 
			
		||||
		station_classes[i].stations = 0;
 | 
			
		||||
 | 
			
		||||
		free(station_classes[i].spec);
 | 
			
		||||
		station_classes[i].spec = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Set up initial data
 | 
			
		||||
	station_classes[0].id = 'DFLT';
 | 
			
		||||
	station_classes[0].name = strdup("Default");
 | 
			
		||||
	station_classes[0].stations = 1;
 | 
			
		||||
	station_classes[0].spec = malloc(sizeof(*station_classes[0].spec));
 | 
			
		||||
	station_classes[0].spec[0] = NULL;
 | 
			
		||||
 | 
			
		||||
	station_classes[1].id = 'WAYP';
 | 
			
		||||
	station_classes[1].name = strdup("Waypoints");
 | 
			
		||||
	station_classes[1].stations = 1;
 | 
			
		||||
	station_classes[1].spec = malloc(sizeof(*station_classes[1].spec));
 | 
			
		||||
	station_classes[1].spec[0] = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Allocate a station class for the given class id.
 | 
			
		||||
 * @param classid A 32 bit value identifying the class.
 | 
			
		||||
 * @return Index into station_classes of allocated class.
 | 
			
		||||
 */
 | 
			
		||||
StationClassID AllocateStationClass(uint32 class)
 | 
			
		||||
{
 | 
			
		||||
	StationClassID i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < STAT_CLASS_MAX; i++) {
 | 
			
		||||
		if (station_classes[i].id == class) {
 | 
			
		||||
			// ClassID is already allocated, so reuse it.
 | 
			
		||||
			return i;
 | 
			
		||||
		} else if (station_classes[i].id == 0) {
 | 
			
		||||
			// This class is empty, so allocate it to the ClassID.
 | 
			
		||||
			station_classes[i].id = class;
 | 
			
		||||
			return i;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DEBUG(grf, 2)("StationClassAllocate: Already allocated %d classes, using default.", STAT_CLASS_MAX);
 | 
			
		||||
	return STAT_CLASS_DFLT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return the number of stations for the given station class.
 | 
			
		||||
 * @param sclass Index of the station class.
 | 
			
		||||
 * @return Number of stations in the class.
 | 
			
		||||
 */
 | 
			
		||||
uint GetNumCustomStations(StationClassID sclass)
 | 
			
		||||
{
 | 
			
		||||
	assert(sclass < STAT_CLASS_MAX);
 | 
			
		||||
	return station_classes[sclass].stations;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tie a station spec to its station class.
 | 
			
		||||
 * @param spec The station spec.
 | 
			
		||||
 */
 | 
			
		||||
void SetCustomStation(StationSpec *spec)
 | 
			
		||||
{
 | 
			
		||||
	StationClass *station_class;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	assert(spec->sclass < STAT_CLASS_MAX);
 | 
			
		||||
	station_class = &station_classes[spec->sclass];
 | 
			
		||||
 | 
			
		||||
	i = station_class->stations++;
 | 
			
		||||
	station_class->spec = realloc(station_class->spec, station_class->stations * sizeof(*station_class->spec));
 | 
			
		||||
 | 
			
		||||
	station_class->spec[i] = spec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Retrieve a station spec from a class.
 | 
			
		||||
 * @param sclass Index of the station class.
 | 
			
		||||
 * @param station The station index with the class.
 | 
			
		||||
 * @return The station spec.
 | 
			
		||||
 */
 | 
			
		||||
const StationSpec *GetCustomStation(StationClassID sclass, uint station)
 | 
			
		||||
{
 | 
			
		||||
	assert(sclass < STAT_CLASS_MAX);
 | 
			
		||||
	if (station < station_classes[sclass].stations)
 | 
			
		||||
		return station_classes[sclass].spec[station];
 | 
			
		||||
 | 
			
		||||
	// If the custom station isn't defined any more, then the GRF file
 | 
			
		||||
	// probably was not loaded.
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										77
									
								
								station_newgrf.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								station_newgrf.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
/* $Id$ */
 | 
			
		||||
 | 
			
		||||
/** @file station_newgrf.h Header file for NewGRF stations */
 | 
			
		||||
 | 
			
		||||
#ifndef STATION_NEWGRF_H
 | 
			
		||||
#define STATION_NEWGRF_H
 | 
			
		||||
 | 
			
		||||
#include "engine.h"
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
	STAT_CLASS_DFLT,     ///< Default station class.
 | 
			
		||||
	STAT_CLASS_WAYP,     ///< Waypoint class.
 | 
			
		||||
	STAT_CLASS_MAX = 16, ///< Maximum number of classes.
 | 
			
		||||
} StationClassID;
 | 
			
		||||
 | 
			
		||||
/* Station layout for given dimensions - it is a two-dimensional array
 | 
			
		||||
 * where index is computed as (x * platforms) + platform. */
 | 
			
		||||
typedef byte *StationLayout;
 | 
			
		||||
 | 
			
		||||
typedef struct stationspec {
 | 
			
		||||
	uint32 grfid; ///< ID of GRF file station belongs to.
 | 
			
		||||
	int localidx; ///< Index within GRF file of station.
 | 
			
		||||
 | 
			
		||||
	StationClassID sclass; ///< The class to which this spec belongs.
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Bitmask of number of platforms available for the station.
 | 
			
		||||
	 * 0..6 correpsond to 1..7, while bit 7 corresponds to >7 platforms.
 | 
			
		||||
	 */
 | 
			
		||||
	byte allowed_platforms;
 | 
			
		||||
	/**
 | 
			
		||||
	 * Bitmask of platform lengths available for the station.
 | 
			
		||||
	 * 0..6 correpsond to 1..7, while bit 7 corresponds to >7 tiles long.
 | 
			
		||||
	 */
 | 
			
		||||
	byte allowed_lengths;
 | 
			
		||||
 | 
			
		||||
	/** Number of tile layouts.
 | 
			
		||||
	 * A minimum of 8 is required is required for stations.
 | 
			
		||||
	 * 0-1 = plain platform
 | 
			
		||||
	 * 2-3 = platform with building
 | 
			
		||||
	 * 4-5 = platform with roof, left side
 | 
			
		||||
	 * 6-7 = platform with roof, right side
 | 
			
		||||
	 */
 | 
			
		||||
	int tiles;
 | 
			
		||||
	DrawTileSprites *renderdata; ///< Array of tile layouts.
 | 
			
		||||
 | 
			
		||||
	byte lengths;
 | 
			
		||||
	byte *platforms;
 | 
			
		||||
	StationLayout **layouts;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * NUM_GLOBAL_CID sprite groups.
 | 
			
		||||
	 * Used for obtaining the sprite offset of custom sprites, and for
 | 
			
		||||
	 * evaluating callbacks.
 | 
			
		||||
	 */
 | 
			
		||||
	SpriteGroup *spritegroup[NUM_GLOBAL_CID];
 | 
			
		||||
} StationSpec;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Struct containing information relating to station classes.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct stationclass {
 | 
			
		||||
	uint32 id;          ///< ID of this class, e.g. 'DFLT', 'WAYP', etc.
 | 
			
		||||
	char *name;         ///< Name of this class.
 | 
			
		||||
	uint stations;      ///< Number of stations in this class.
 | 
			
		||||
	StationSpec **spec; ///< Array of station specifications.
 | 
			
		||||
} StationClass;
 | 
			
		||||
 | 
			
		||||
void ResetStationClasses(void);
 | 
			
		||||
StationClassID AllocateStationClass(uint32 class);
 | 
			
		||||
void SetStationClassName(StationClassID sclass, const char *name);
 | 
			
		||||
uint GetNumCustomStations(StationClassID sclass);
 | 
			
		||||
 | 
			
		||||
void SetCustomStation(StationSpec *spec);
 | 
			
		||||
const StationSpec *GetCustomStation(StationClassID sclass, uint station);
 | 
			
		||||
 | 
			
		||||
#endif /* STATION_NEWGRF_H */
 | 
			
		||||
							
								
								
									
										16
									
								
								waypoint.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								waypoint.c
									
									
									
									
									
								
							@@ -154,7 +154,7 @@ static Waypoint *FindDeletedWaypointCloseTo(TileIndex tile)
 | 
			
		||||
/** Convert existing rail to waypoint. Eg build a waypoint station over
 | 
			
		||||
 * piece of rail
 | 
			
		||||
 * @param x,y coordinates where waypoint will be built
 | 
			
		||||
 * @param p1 graphics for waypoint type, bit 8 signifies custom waypoint gfx (& 0x100)
 | 
			
		||||
 * @param p1 graphics for waypoint type, 0 indicates standard graphics
 | 
			
		||||
 * @param p2 unused
 | 
			
		||||
 *
 | 
			
		||||
 * @todo When checking for the tile slope,
 | 
			
		||||
@@ -170,7 +170,7 @@ int32 CmdBuildTrainWaypoint(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 | 
			
		||||
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 | 
			
		||||
 | 
			
		||||
	/* if custom gfx are used, make sure it is within bounds */
 | 
			
		||||
	if (p1 > 0x100 + (uint)GetCustomStationsCount(STAT_CLASS_WAYP)) return CMD_ERROR;
 | 
			
		||||
	if (p1 >= GetNumCustomStations(STAT_CLASS_WAYP)) return CMD_ERROR;
 | 
			
		||||
 | 
			
		||||
	if (!IsTileType(tile, MP_RAILWAY) || ((dir = 0, _m[tile].m5 != 1) && (dir = 1, _m[tile].m5 != 2)))
 | 
			
		||||
		return_cmd_error(STR_1005_NO_SUITABLE_RAILROAD_TRACK);
 | 
			
		||||
@@ -200,10 +200,10 @@ int32 CmdBuildTrainWaypoint(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 | 
			
		||||
	if (flags & DC_EXEC) {
 | 
			
		||||
		bool reserved = PBSTileReserved(tile) != 0;
 | 
			
		||||
		ModifyTile(tile, MP_MAP5, RAIL_TYPE_WAYPOINT | dir);
 | 
			
		||||
		if (--p1 & 0x100) { // waypoint type 0 uses default graphics
 | 
			
		||||
		if (p1 > 0) { // waypoint type 0 uses default graphics
 | 
			
		||||
			// custom graphics
 | 
			
		||||
			_m[tile].m3 |= 16;
 | 
			
		||||
			_m[tile].m4 = p1 & 0xff;
 | 
			
		||||
			_m[tile].m4 = (p1 - 1) & 0xff;
 | 
			
		||||
		}
 | 
			
		||||
		if (reserved) {
 | 
			
		||||
			PBSReserveTrack(tile, dir);
 | 
			
		||||
@@ -387,14 +387,14 @@ void DrawWaypointSprite(int x, int y, int stat_id, RailType railtype)
 | 
			
		||||
	x += 33;
 | 
			
		||||
	y += 17;
 | 
			
		||||
 | 
			
		||||
	/* draw default waypoint graphics of ID 0 */
 | 
			
		||||
	if (stat_id == 0) {
 | 
			
		||||
	stat = GetCustomStation(STAT_CLASS_WAYP, stat_id);
 | 
			
		||||
	if (stat == NULL) {
 | 
			
		||||
		// stat is NULL for default waypoints and when waypoint graphics are
 | 
			
		||||
		// not loaded.
 | 
			
		||||
		DrawDefaultWaypointSprite(x, y, railtype);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	stat = GetCustomStation(STAT_CLASS_WAYP, stat_id - 1);
 | 
			
		||||
	assert(stat);
 | 
			
		||||
	relocation = GetCustomStationRelocation(stat, NULL, 1);
 | 
			
		||||
	// emulate station tile - open with building
 | 
			
		||||
	// add 1 to get the other direction
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ struct Waypoint {
 | 
			
		||||
	ViewportSign sign;
 | 
			
		||||
	uint16 build_date;
 | 
			
		||||
	byte stat_id;
 | 
			
		||||
	uint32 grfid;
 | 
			
		||||
	byte deleted;          // this is a delete counter. when it reaches 0, the waypoint struct is deleted.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user