mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-06 14:27:16 +00:00
(svn r4473) - Newstations:
- Alter parameters of CMD_BUILD_RAILROAD_STATION to accept a custom station class and id. - Add a dynamically allocated list of custom stations that the SpecIndex (m4) references.
This commit is contained in:
parent
225f7dcb62
commit
de84d6338d
103
newgrf_station.c
103
newgrf_station.c
@ -7,6 +7,7 @@
|
||||
#include "debug.h"
|
||||
#include "sprite.h"
|
||||
#include "station.h"
|
||||
#include "station_map.h"
|
||||
#include "newgrf_station.h"
|
||||
|
||||
static StationClass station_classes[STAT_CLASS_MAX];
|
||||
@ -69,6 +70,17 @@ StationClassID AllocateStationClass(uint32 class)
|
||||
return STAT_CLASS_DFLT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of station classes in use.
|
||||
* @return Number of station classes.
|
||||
*/
|
||||
uint GetNumStationClasses(void)
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i < STAT_CLASS_MAX && station_classes[i].id != 0; i++);
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of stations for the given station class.
|
||||
* @param sclass Index of the station class.
|
||||
@ -198,3 +210,94 @@ uint32 GetCustomStationRelocation(const StationSpec *spec, const Station *st, by
|
||||
* emergency measure. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allocate a StationSpec to a Station. This is called once per build operation.
|
||||
* @param spec StationSpec to allocate.
|
||||
* @param st Station to allocate it to.
|
||||
* @param exec Whether to actually allocate the spec.
|
||||
* @return Index within the Station's spec list, or -1 if the allocation failed.
|
||||
*/
|
||||
int AllocateSpecToStation(const StationSpec *spec, Station *st, bool exec)
|
||||
{
|
||||
uint i;
|
||||
|
||||
if (spec == NULL) return 0;
|
||||
|
||||
/* Check if this spec has already been allocated */
|
||||
for (i = 1; i < st->num_specs && i < 256; i++) {
|
||||
if (st->speclist[i].spec == spec) return i;
|
||||
}
|
||||
|
||||
for (i = 1; i < st->num_specs && i < 256; i++) {
|
||||
if (st->speclist[i].spec == NULL && st->speclist[i].grfid == 0) break;
|
||||
}
|
||||
|
||||
if (i < 256) {
|
||||
if (exec) {
|
||||
if (i >= st->num_specs) {
|
||||
st->num_specs = i + 1;
|
||||
st->speclist = realloc(st->speclist, st->num_specs * sizeof(*st->speclist));
|
||||
|
||||
if (st->num_specs == 2) {
|
||||
/* Initial allocation */
|
||||
st->speclist[0].spec = NULL;
|
||||
st->speclist[0].grfid = 0;
|
||||
st->speclist[0].localidx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
st->speclist[i].spec = spec;
|
||||
st->speclist[i].grfid = spec->grfid;
|
||||
st->speclist[i].localidx = spec->localidx;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/** Deallocate a StationSpec from a Station. Called when removing a single station tile.
|
||||
* @param st Station to work with.
|
||||
* @param specindex Index of the custom station within the Station's spec list.
|
||||
* @return Indicates whether the StationSpec was deallocated.
|
||||
*/
|
||||
bool DeallocateSpecFromStation(Station *st, byte specindex)
|
||||
{
|
||||
bool freeable = true;
|
||||
|
||||
/* specindex of 0 (default) is never freeable */
|
||||
if (specindex == 0) return false;
|
||||
|
||||
/* Check all tiles over the station to check if the specindex is still in use */
|
||||
BEGIN_TILE_LOOP(tile, st->trainst_w, st->trainst_h, st->train_tile) {
|
||||
if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == st->index && IsRailwayStation(tile) && GetCustomStationSpecIndex(tile) == specindex) {
|
||||
freeable = false;
|
||||
break;
|
||||
}
|
||||
} END_TILE_LOOP(tile, st->trainst_w, st->trainst_h, st->train_tile)
|
||||
|
||||
if (freeable) {
|
||||
/* This specindex is no longer in use, so deallocate it */
|
||||
st->speclist[specindex].spec = NULL;
|
||||
st->speclist[specindex].grfid = 0;
|
||||
st->speclist[specindex].localidx = 0;
|
||||
|
||||
/* If this was the highest spec index, reallocate */
|
||||
if (specindex == st->num_specs - 1) {
|
||||
for (; st->speclist[st->num_specs - 1].grfid == 0 && st->num_specs > 1; st->num_specs--);
|
||||
|
||||
if (st->num_specs > 1) {
|
||||
st->speclist = realloc(st->speclist, st->num_specs * sizeof(*st->speclist));
|
||||
} else {
|
||||
free(st->speclist);
|
||||
st->num_specs = 0;
|
||||
st->speclist = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return freeable;
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ typedef struct stationclass {
|
||||
void ResetStationClasses(void);
|
||||
StationClassID AllocateStationClass(uint32 class);
|
||||
void SetStationClassName(StationClassID sclass, const char *name);
|
||||
uint GetNumStationClasses(void);
|
||||
uint GetNumCustomStations(StationClassID sclass);
|
||||
|
||||
void SetCustomStation(StationSpec *spec);
|
||||
@ -94,4 +95,10 @@ const StationSpec *GetCustomStation(StationClassID sclass, uint station);
|
||||
* structure is used for variational sprite groups. */
|
||||
uint32 GetCustomStationRelocation(const StationSpec *spec, const Station *st, byte ctype);
|
||||
|
||||
/* Allocate a StationSpec to a Station. This is called once per build operation. */
|
||||
int AllocateSpecToStation(const StationSpec *spec, Station *st, bool exec);
|
||||
|
||||
/* Deallocate a StationSpec from a Station. Called when removing a single station tile. */
|
||||
bool DeallocateSpecFromStation(Station *st, byte specindex);
|
||||
|
||||
#endif /* NEWGRF_STATION_H */
|
||||
|
10
station.h
10
station.h
@ -41,6 +41,12 @@ typedef struct RoadStop {
|
||||
struct RoadStop *prev;
|
||||
} RoadStop;
|
||||
|
||||
typedef struct StationSpecList {
|
||||
const StationSpec *spec;
|
||||
uint32 grfid; /// GRF ID of this custom station
|
||||
uint8 localidx; /// Station ID within GRF of station
|
||||
} StationSpecList;
|
||||
|
||||
struct Station {
|
||||
TileIndex xy;
|
||||
RoadStop *bus_stops;
|
||||
@ -65,6 +71,10 @@ struct Station {
|
||||
// trainstation width/height
|
||||
byte trainst_w, trainst_h;
|
||||
|
||||
/** List of custom stations (StationSpecs) allocated to the station */
|
||||
uint num_specs;
|
||||
StationSpecList *speclist;
|
||||
|
||||
uint16 build_date;
|
||||
|
||||
//uint16 airport_flags;
|
||||
|
@ -50,6 +50,17 @@ static void StationPoolNewBlock(uint start_item)
|
||||
FOR_ALL_STATIONS_FROM(st, start_item) st->index = start_item++;
|
||||
}
|
||||
|
||||
static void StationPoolCleanBlock(uint start_item, uint end_item)
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = start_item; i <= end_item; i++) {
|
||||
Station *st = GetStation(i);
|
||||
free(st->speclist);
|
||||
st->speclist = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called if a new block is added to the roadstop-pool
|
||||
*/
|
||||
@ -61,7 +72,7 @@ static void RoadStopPoolNewBlock(uint start_item)
|
||||
}
|
||||
|
||||
/* Initialize the station-pool and roadstop-pool */
|
||||
MemoryPool _station_pool = { "Stations", STATION_POOL_MAX_BLOCKS, STATION_POOL_BLOCK_SIZE_BITS, sizeof(Station), &StationPoolNewBlock, NULL, 0, 0, NULL };
|
||||
MemoryPool _station_pool = { "Stations", STATION_POOL_MAX_BLOCKS, STATION_POOL_BLOCK_SIZE_BITS, sizeof(Station), &StationPoolNewBlock, &StationPoolCleanBlock, 0, 0, NULL };
|
||||
MemoryPool _roadstop_pool = { "RoadStop", ROADSTOP_POOL_MAX_BLOCKS, ROADSTOP_POOL_BLOCK_SIZE_BITS, sizeof(RoadStop), &RoadStopPoolNewBlock, NULL, 0, 0, NULL };
|
||||
|
||||
|
||||
@ -939,8 +950,8 @@ static void GetStationLayout(byte *layout, int numtracks, int plat_len, const St
|
||||
* - p1 = (bit 16-23) - platform length
|
||||
* @param p2 various bitstuffed elements
|
||||
* - p2 = (bit 0- 3) - railtype (p2 & 0xF)
|
||||
* - p2 = (bit 4) - set for custom station (p2 & 0x10)
|
||||
* - p2 = (bit 8-..) - custom station id (p2 >> 8)
|
||||
* - p2 = (bit 8-15) - custom station class
|
||||
* - p2 = (bit 16-23) - custom station id
|
||||
*/
|
||||
int32 CmdBuildRailroadStation(TileIndex tile_org, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
@ -951,6 +962,8 @@ int32 CmdBuildRailroadStation(TileIndex tile_org, uint32 flags, uint32 p1, uint3
|
||||
int plat_len, numtracks;
|
||||
Axis axis;
|
||||
uint finalvalues[3];
|
||||
const StationSpec *statspec;
|
||||
int specindex;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
@ -1025,10 +1038,17 @@ int32 CmdBuildRailroadStation(TileIndex tile_org, uint32 flags, uint32 p1, uint3
|
||||
if (flags & DC_EXEC) StationInitialize(st, tile_org);
|
||||
}
|
||||
|
||||
/* Check if the given station class is valid */
|
||||
if (GB(p2, 8, 8) >= STAT_CLASS_MAX) return CMD_ERROR;
|
||||
|
||||
/* Check if we can allocate a custom stationspec to this station */
|
||||
statspec = GetCustomStation(GB(p2, 8, 8), GB(p2, 16, 8));
|
||||
specindex = AllocateSpecToStation(statspec, st, flags & DC_EXEC);
|
||||
if (specindex == -1) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
TileIndexDiff tile_delta;
|
||||
byte *layout_ptr;
|
||||
const StationSpec *statspec;
|
||||
Track track;
|
||||
|
||||
// Now really clear the land below the station
|
||||
@ -1050,7 +1070,6 @@ int32 CmdBuildRailroadStation(TileIndex tile_org, uint32 flags, uint32 p1, uint3
|
||||
tile_delta = (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
|
||||
track = (axis == AXIS_X ? TRACK_X : TRACK_Y);
|
||||
|
||||
statspec = (p2 & 0x10) != 0 ? GetCustomStation(STAT_CLASS_DFLT, p2 >> 8) : NULL;
|
||||
layout_ptr = alloca(numtracks * plat_len);
|
||||
GetStationLayout(layout_ptr, numtracks, plat_len, statspec);
|
||||
|
||||
@ -1060,8 +1079,7 @@ int32 CmdBuildRailroadStation(TileIndex tile_org, uint32 flags, uint32 p1, uint3
|
||||
do {
|
||||
|
||||
MakeRailStation(tile, st->owner, st->index, axis, *layout_ptr++, GB(p2, 0, 4));
|
||||
|
||||
if (HASBIT(p2, 4)) SetCustomStationSpecIndex(tile, GB(p2, 8, 8));
|
||||
SetCustomStationSpecIndex(tile, specindex);
|
||||
|
||||
tile += tile_delta;
|
||||
} while (--w);
|
||||
@ -1158,9 +1176,13 @@ int32 CmdRemoveFromRailroadStation(TileIndex tile, uint32 flags, uint32 p1, uint
|
||||
|
||||
// if we reached here, it means we can actually delete it. do that.
|
||||
if (flags & DC_EXEC) {
|
||||
uint specindex = GetCustomStationSpecIndex(tile);
|
||||
Track track = GetRailStationTrack(tile);
|
||||
DoClearSquare(tile);
|
||||
SetSignalsOnBothDir(tile, track);
|
||||
|
||||
DeallocateSpecFromStation(st, specindex);
|
||||
|
||||
// now we need to make the "spanned" area of the railway station smaller if we deleted something at the edges.
|
||||
// we also need to adjust train_tile.
|
||||
MakeRailwayStationAreaSmaller(st);
|
||||
@ -1252,6 +1274,10 @@ static int32 RemoveRailroadStation(Station *st, TileIndex tile, uint32 flags)
|
||||
st->train_tile = 0;
|
||||
st->facilities &= ~FACIL_TRAIN;
|
||||
|
||||
free(st->speclist);
|
||||
st->num_specs = 0;
|
||||
st->speclist = NULL;
|
||||
|
||||
UpdateStationVirtCoordDirty(st);
|
||||
DeleteStationIfEmpty(st);
|
||||
}
|
||||
@ -1936,12 +1962,12 @@ static void DrawTile_Station(TileInfo *ti)
|
||||
|
||||
if (IsCustomStationSpecIndex(ti->tile)) {
|
||||
// look for customization
|
||||
const StationSpec *statspec = GetCustomStation(STAT_CLASS_DFLT, GetCustomStationSpecIndex(ti->tile));
|
||||
const Station *st = GetStationByTile(ti->tile);
|
||||
const StationSpec *statspec = st->speclist[GetCustomStationSpecIndex(ti->tile)].spec;
|
||||
|
||||
//debug("Cust-o-mized %p", statspec);
|
||||
|
||||
if (statspec != NULL) {
|
||||
const Station* st = GetStationByTile(ti->tile);
|
||||
uint tile = GetStationGfx(ti->tile);
|
||||
|
||||
relocation = GetCustomStationRelocation(statspec, st, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user