(svn r1407) -Codechange: changed a lot around _stations, _vehicles, _towns and _industries

(in prepare of dynamic arrays):
  - DEREF_XXX is changed into GetXXX
  - All direct call are directed via GetXXX
  - struct Industry has now an index-field
  - ENUM'd some stuff
  - Replaced home built loops with FOR_ALL_XXX
  - Added _stations_size, _vehicles_size, ... which gives the length of the
    array (which will be dynamic in the near future)
  - Changed lengtof(XXX) to _XXX_size (e.g. _stations_size)
  - Removed all endof(XXX) (because mostly it was part of a FOR_ALL_XXX)
  - Made the sort-functions of all 4 dynamic
  - Made all 4 Initialize functions more of the same
  - Some minor tab-fixing and stuff
  (tnx to Tron for proof-reading my 100kb patch ;))

  Note for all: please do NOT directly call _stations, _vehicles, _towns and
  _industries, but use the right wrapper to access them. Thank you.
  Ps: please also do not use 'v++', where v is of type Vehicle *.
This commit is contained in:
truelight 2005-01-06 22:31:58 +00:00
parent a4111363c0
commit 63e97754fb
35 changed files with 567 additions and 412 deletions

29
ai.c
View File

@ -69,10 +69,11 @@ static void AiCase1(Player *p)
static void AiStateVehLoop(Player *p) static void AiStateVehLoop(Player *p)
{ {
Vehicle *v; Vehicle *v;
uint index;
v = p->ai.cur_veh == NULL ? _vehicles : p->ai.cur_veh+1; index = (p->ai.cur_veh == NULL) ? 0 : p->ai.cur_veh->index + 1;
for (;v != endof(_vehicles); v++) { FOR_ALL_VEHICLES_FROM(v, index) {
if (v->type == 0 || v->owner != _current_player) if (v->type == 0 || v->owner != _current_player)
continue; continue;
@ -297,7 +298,7 @@ static void AiHandleReplaceTrain(Player *p)
if (DoCommandByTile(0, v->index, 2, DC_EXEC, CMD_SELL_RAIL_WAGON) != CMD_ERROR && if (DoCommandByTile(0, v->index, 2, DC_EXEC, CMD_SELL_RAIL_WAGON) != CMD_ERROR &&
DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE) != CMD_ERROR) { DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE) != CMD_ERROR) {
veh = _new_train_id; veh = _new_train_id;
AiRestoreVehicleOrders(&_vehicles[veh], orderbak); AiRestoreVehicleOrders(GetVehicle(veh), orderbak);
DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_TRAIN); DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_TRAIN);
DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT); DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT);
@ -325,7 +326,7 @@ static void AiHandleReplaceRoadVeh(Player *p)
if (DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH) != CMD_ERROR && if (DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH) != CMD_ERROR &&
DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH) != CMD_ERROR) { DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH) != CMD_ERROR) {
veh = _new_roadveh_id; veh = _new_roadveh_id;
AiRestoreVehicleOrders(&_vehicles[veh], orderbak); AiRestoreVehicleOrders(GetVehicle(veh), orderbak);
DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_ROADVEH); DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_ROADVEH);
DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT); DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT);
@ -353,7 +354,7 @@ static void AiHandleReplaceAircraft(Player *p)
if (DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_AIRCRAFT) != CMD_ERROR && if (DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_AIRCRAFT) != CMD_ERROR &&
DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT) != CMD_ERROR) { DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT) != CMD_ERROR) {
veh = _new_aircraft_id; veh = _new_aircraft_id;
AiRestoreVehicleOrders(&_vehicles[veh], orderbak); AiRestoreVehicleOrders(GetVehicle(veh), orderbak);
DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_AIRCRAFT); DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_AIRCRAFT);
DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT); DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT);
@ -413,12 +414,12 @@ typedef struct FoundRoute {
} FoundRoute; } FoundRoute;
static Town *AiFindRandomTown() { static Town *AiFindRandomTown() {
Town *t = DEREF_TOWN(RandomRange(_total_towns)); Town *t = GetTown(RandomRange(_total_towns));
return (t->xy != 0) ? t : NULL; return (t->xy != 0) ? t : NULL;
} }
static Industry *AiFindRandomIndustry() { static Industry *AiFindRandomIndustry() {
Industry *i = DEREF_INDUSTRY(RandomRange(_total_industries)); Industry *i = GetIndustry(RandomRange(_total_industries));
return (i->xy != 0) ? i : NULL; return (i->xy != 0) ? i : NULL;
} }
@ -447,16 +448,16 @@ static void AiFindSubsidyIndustryRoute(FoundRoute *fr)
return; return;
fr->cargo = cargo; fr->cargo = cargo;
fr->from = from = DEREF_INDUSTRY(s->from); fr->from = from = GetIndustry(s->from);
if (cargo == CT_GOODS || cargo == CT_FOOD) { if (cargo == CT_GOODS || cargo == CT_FOOD) {
to_tow = DEREF_TOWN(s->to); to_tow = GetTown(s->to);
if (to_tow->population < (uint32)(cargo == CT_FOOD ? 200 : 900)) if (to_tow->population < (uint32)(cargo == CT_FOOD ? 200 : 900))
return; // error return; // error
fr->to = to_tow; fr->to = to_tow;
to_xy = to_tow->xy; to_xy = to_tow->xy;
} else { } else {
to_ind = DEREF_INDUSTRY(s->to); to_ind = GetIndustry(s->to);
fr->to = to_ind; fr->to = to_ind;
to_xy = to_ind->xy; to_xy = to_ind->xy;
} }
@ -485,8 +486,8 @@ static void AiFindSubsidyPassengerRoute(FoundRoute *fr)
return; return;
fr->cargo = s->cargo_type; fr->cargo = s->cargo_type;
fr->from = from = DEREF_TOWN(s->from); fr->from = from = GetTown(s->from);
fr->to = to = DEREF_TOWN(s->to); fr->to = to = GetTown(s->to);
// They must be big enough // They must be big enough
if (from->population < 400 || to->population < 400) if (from->population < 400 || to->population < 400)
@ -1416,7 +1417,7 @@ static void AiWantOilRigAircraftRoute(Player *p)
t = AiFindRandomTown(); t = AiFindRandomTown();
if (t != NULL) { if (t != NULL) {
// Find a random oil rig industry // Find a random oil rig industry
in = DEREF_INDUSTRY(RandomRange(_total_industries)); in = GetIndustry(RandomRange(_total_industries));
if (in != NULL && in->type == IT_OIL_RIG) { if (in != NULL && in->type == IT_OIL_RIG) {
if (GetTileDist(t->xy, in->xy) < 60) if (GetTileDist(t->xy, in->xy) < 60)
break; break;
@ -2412,7 +2413,7 @@ handle_nocash:
loco_id = _new_train_id; loco_id = _new_train_id;
// Sell a vehicle if the train is double headed. // Sell a vehicle if the train is double headed.
v = &_vehicles[loco_id]; v = GetVehicle(loco_id);
if (v->next != NULL) { if (v->next != NULL) {
i = p->ai.wagon_list[p->ai.num_wagons*2-2]; i = p->ai.wagon_list[p->ai.num_wagons*2-2];
p->ai.wagon_list[p->ai.num_wagons*2-2] = INVALID_VEHICLE; p->ai.wagon_list[p->ai.num_wagons*2-2] = INVALID_VEHICLE;

View File

@ -185,7 +185,7 @@ static void AiNew_State_ActionDone(Player *p) {
// Check if a city or industry is good enough to start a route there // Check if a city or industry is good enough to start a route there
static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) { static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) {
if (type == AI_CITY) { if (type == AI_CITY) {
Town *t = DEREF_TOWN(ic); Town *t = GetTown(ic);
Station *st; Station *st;
int count = 0; int count = 0;
int j = 0; int j = 0;
@ -247,7 +247,7 @@ static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) {
return true; return true;
} }
if (type == AI_INDUSTRY) { if (type == AI_INDUSTRY) {
Industry *i = DEREF_INDUSTRY(ic); Industry *i = GetIndustry(ic);
Station *st; Station *st;
int count = 0; int count = 0;
int j = 0; int j = 0;
@ -405,16 +405,16 @@ static void AiNew_State_LocateRoute(Player *p) {
// is. // is.
if (p->ainew.from_type == AI_CITY && p->ainew.tbt == AI_BUS) { if (p->ainew.from_type == AI_CITY && p->ainew.tbt == AI_BUS) {
int max_cargo = DEREF_TOWN(p->ainew.from_ic)->max_pass + DEREF_TOWN(p->ainew.temp)->max_pass; int max_cargo = GetTown(p->ainew.from_ic)->max_pass + GetTown(p->ainew.temp)->max_pass;
max_cargo -= DEREF_TOWN(p->ainew.from_ic)->act_pass + DEREF_TOWN(p->ainew.temp)->act_pass; max_cargo -= GetTown(p->ainew.from_ic)->act_pass + GetTown(p->ainew.temp)->act_pass;
// max_cargo is now the amount of cargo we can move between the two cities // max_cargo is now the amount of cargo we can move between the two cities
// If it is more than the distance, we allow it // If it is more than the distance, we allow it
if (GetTileDist(DEREF_TOWN(p->ainew.from_ic)->xy, DEREF_TOWN(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_BUS_CARGO_DISTANCE) { if (GetTileDist(GetTown(p->ainew.from_ic)->xy, GetTown(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_BUS_CARGO_DISTANCE) {
// We found a good city/industry, save the data of it // We found a good city/industry, save the data of it
p->ainew.to_ic = p->ainew.temp; p->ainew.to_ic = p->ainew.temp;
p->ainew.state = AI_STATE_FIND_STATION; p->ainew.state = AI_STATE_FIND_STATION;
DEBUG(ai,1)("[AiNew - LocateRoute] Found bus-route of %d tiles long (from %d to %d)",GetTileDist(DEREF_TOWN(p->ainew.from_ic)->xy, DEREF_TOWN(p->ainew.temp)->xy), p->ainew.from_ic, p->ainew.temp); DEBUG(ai,1)("[AiNew - LocateRoute] Found bus-route of %d tiles long (from %d to %d)",GetTileDist(GetTown(p->ainew.from_ic)->xy, GetTown(p->ainew.temp)->xy), p->ainew.from_ic, p->ainew.temp);
p->ainew.from_tile = 0; p->ainew.from_tile = 0;
p->ainew.to_tile = 0; p->ainew.to_tile = 0;
@ -427,12 +427,12 @@ static void AiNew_State_LocateRoute(Player *p) {
int i; int i;
// TODO: in max_cargo, also check other cargo (beside [0]) // TODO: in max_cargo, also check other cargo (beside [0])
// First we check if the from_ic produces cargo that this ic accepts // First we check if the from_ic produces cargo that this ic accepts
if (DEREF_INDUSTRY(p->ainew.from_ic)->produced_cargo[0] != 0xFF && DEREF_INDUSTRY(p->ainew.from_ic)->total_production[0] != 0) { if (GetIndustry(p->ainew.from_ic)->produced_cargo[0] != 0xFF && GetIndustry(p->ainew.from_ic)->total_production[0] != 0) {
for (i=0;i<3;i++) { for (i=0;i<3;i++) {
if (DEREF_INDUSTRY(p->ainew.temp)->accepts_cargo[i] == 0xFF) break; if (GetIndustry(p->ainew.temp)->accepts_cargo[i] == 0xFF) break;
if (DEREF_INDUSTRY(p->ainew.from_ic)->produced_cargo[0] == DEREF_INDUSTRY(p->ainew.temp)->accepts_cargo[i]) { if (GetIndustry(p->ainew.from_ic)->produced_cargo[0] == GetIndustry(p->ainew.temp)->accepts_cargo[i]) {
// Found a compatbiel industry // Found a compatbiel industry
max_cargo = DEREF_INDUSTRY(p->ainew.from_ic)->total_production[0] - DEREF_INDUSTRY(p->ainew.from_ic)->total_transported[0]; max_cargo = GetIndustry(p->ainew.from_ic)->total_production[0] - GetIndustry(p->ainew.from_ic)->total_transported[0];
found = true; found = true;
p->ainew.from_deliver = true; p->ainew.from_deliver = true;
p->ainew.to_deliver = false; p->ainew.to_deliver = false;
@ -440,14 +440,14 @@ static void AiNew_State_LocateRoute(Player *p) {
} }
} }
} }
if (!found && DEREF_INDUSTRY(p->ainew.temp)->produced_cargo[0] != 0xFF && DEREF_INDUSTRY(p->ainew.temp)->total_production[0] != 0) { if (!found && GetIndustry(p->ainew.temp)->produced_cargo[0] != 0xFF && GetIndustry(p->ainew.temp)->total_production[0] != 0) {
// If not check if the current ic produces cargo that the from_ic accepts // If not check if the current ic produces cargo that the from_ic accepts
for (i=0;i<3;i++) { for (i=0;i<3;i++) {
if (DEREF_INDUSTRY(p->ainew.from_ic)->accepts_cargo[i] == 0xFF) break; if (GetIndustry(p->ainew.from_ic)->accepts_cargo[i] == 0xFF) break;
if (DEREF_INDUSTRY(p->ainew.temp)->produced_cargo[0] == DEREF_INDUSTRY(p->ainew.from_ic)->accepts_cargo[i]) { if (GetIndustry(p->ainew.temp)->produced_cargo[0] == GetIndustry(p->ainew.from_ic)->accepts_cargo[i]) {
// Found a compatbiel industry // Found a compatbiel industry
found = true; found = true;
max_cargo = DEREF_INDUSTRY(p->ainew.temp)->total_production[0] - DEREF_INDUSTRY(p->ainew.from_ic)->total_transported[0]; max_cargo = GetIndustry(p->ainew.temp)->total_production[0] - GetIndustry(p->ainew.from_ic)->total_transported[0];
p->ainew.from_deliver = false; p->ainew.from_deliver = false;
p->ainew.to_deliver = true; p->ainew.to_deliver = true;
break; break;
@ -457,17 +457,17 @@ static void AiNew_State_LocateRoute(Player *p) {
if (found) { if (found) {
// Yeah, they are compatible!!! // Yeah, they are compatible!!!
// Check the length against the amount of goods // Check the length against the amount of goods
if (GetTileDist(DEREF_INDUSTRY(p->ainew.from_ic)->xy, DEREF_INDUSTRY(p->ainew.temp)->xy) > AI_LOCATEROUTE_TRUCK_MIN_DISTANCE && if (GetTileDist(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy) > AI_LOCATEROUTE_TRUCK_MIN_DISTANCE &&
GetTileDist(DEREF_INDUSTRY(p->ainew.from_ic)->xy, DEREF_INDUSTRY(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE) { GetTileDist(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE) {
p->ainew.to_ic = p->ainew.temp; p->ainew.to_ic = p->ainew.temp;
if (p->ainew.from_deliver) { if (p->ainew.from_deliver) {
p->ainew.cargo = DEREF_INDUSTRY(p->ainew.from_ic)->produced_cargo[0]; p->ainew.cargo = GetIndustry(p->ainew.from_ic)->produced_cargo[0];
} else { } else {
p->ainew.cargo = DEREF_INDUSTRY(p->ainew.temp)->produced_cargo[0]; p->ainew.cargo = GetIndustry(p->ainew.temp)->produced_cargo[0];
} }
p->ainew.state = AI_STATE_FIND_STATION; p->ainew.state = AI_STATE_FIND_STATION;
DEBUG(ai,1)("[AiNew - LocateRoute] Found truck-route of %d tiles long (from %d to %d)",GetTileDist(DEREF_INDUSTRY(p->ainew.from_ic)->xy, DEREF_INDUSTRY(p->ainew.temp)->xy), p->ainew.from_ic, p->ainew.temp); DEBUG(ai,1)("[AiNew - LocateRoute] Found truck-route of %d tiles long (from %d to %d)",GetTileDist(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy), p->ainew.from_ic, p->ainew.temp);
p->ainew.from_tile = 0; p->ainew.from_tile = 0;
p->ainew.to_tile = 0; p->ainew.to_tile = 0;
@ -506,7 +506,7 @@ static bool AiNew_CheckVehicleStation(Player *p, Station *st) {
if (sched != NULL) { if (sched != NULL) {
for (; sched->type != OT_NOTHING; ++sched) { for (; sched->type != OT_NOTHING; ++sched) {
if (sched->type == OT_GOTO_STATION && if (sched->type == OT_GOTO_STATION &&
DEREF_STATION(sched->station) == st) { GetStation(sched->station) == st) {
// This vehicle has this city in his list // This vehicle has this city in his list
count++; count++;
} }
@ -533,19 +533,19 @@ static void AiNew_State_FindStation(Player *p) {
if (p->ainew.from_tile == 0) { if (p->ainew.from_tile == 0) {
// First we scan for a station in the from-city // First we scan for a station in the from-city
if (p->ainew.from_type == AI_CITY) { if (p->ainew.from_type == AI_CITY) {
town = DEREF_TOWN(p->ainew.from_ic); town = GetTown(p->ainew.from_ic);
tile = town->xy; tile = town->xy;
} else { } else {
industry = DEREF_INDUSTRY(p->ainew.from_ic); industry = GetIndustry(p->ainew.from_ic);
tile = industry->xy; tile = industry->xy;
} }
} else if (p->ainew.to_tile == 0) { } else if (p->ainew.to_tile == 0) {
// Second we scan for a station in the to-city // Second we scan for a station in the to-city
if (p->ainew.to_type == AI_CITY) { if (p->ainew.to_type == AI_CITY) {
town = DEREF_TOWN(p->ainew.to_ic); town = GetTown(p->ainew.to_ic);
tile = town->xy; tile = town->xy;
} else { } else {
industry = DEREF_INDUSTRY(p->ainew.to_ic); industry = GetIndustry(p->ainew.to_ic);
tile = industry->xy; tile = industry->xy;
} }
} else { } else {
@ -682,8 +682,8 @@ static void AiNew_State_FindPath(Player *p) {
// Init path_info // Init path_info
if (p->ainew.from_tile == AI_STATION_RANGE) { if (p->ainew.from_tile == AI_STATION_RANGE) {
// For truck routes we take a range around the industry // For truck routes we take a range around the industry
p->ainew.path_info.start_tile_tl = DEREF_INDUSTRY(p->ainew.from_ic)->xy - TILE_XY(1,1); p->ainew.path_info.start_tile_tl = GetIndustry(p->ainew.from_ic)->xy - TILE_XY(1,1);
p->ainew.path_info.start_tile_br = DEREF_INDUSTRY(p->ainew.from_ic)->xy + TILE_XY(DEREF_INDUSTRY(p->ainew.from_ic)->width, DEREF_INDUSTRY(p->ainew.from_ic)->height) + TILE_XY(1,1); p->ainew.path_info.start_tile_br = GetIndustry(p->ainew.from_ic)->xy + TILE_XY(GetIndustry(p->ainew.from_ic)->width, GetIndustry(p->ainew.from_ic)->height) + TILE_XY(1,1);
p->ainew.path_info.start_direction = p->ainew.from_direction; p->ainew.path_info.start_direction = p->ainew.from_direction;
} else { } else {
p->ainew.path_info.start_tile_tl = p->ainew.from_tile; p->ainew.path_info.start_tile_tl = p->ainew.from_tile;
@ -692,8 +692,8 @@ static void AiNew_State_FindPath(Player *p) {
} }
if (p->ainew.to_tile == AI_STATION_RANGE) { if (p->ainew.to_tile == AI_STATION_RANGE) {
p->ainew.path_info.end_tile_tl = DEREF_INDUSTRY(p->ainew.to_ic)->xy - TILE_XY(1,1); p->ainew.path_info.end_tile_tl = GetIndustry(p->ainew.to_ic)->xy - TILE_XY(1,1);
p->ainew.path_info.end_tile_br = DEREF_INDUSTRY(p->ainew.to_ic)->xy + TILE_XY(DEREF_INDUSTRY(p->ainew.to_ic)->width, DEREF_INDUSTRY(p->ainew.to_ic)->height) + TILE_XY(1,1); p->ainew.path_info.end_tile_br = GetIndustry(p->ainew.to_ic)->xy + TILE_XY(GetIndustry(p->ainew.to_ic)->width, GetIndustry(p->ainew.to_ic)->height) + TILE_XY(1,1);
p->ainew.path_info.end_direction = p->ainew.to_direction; p->ainew.path_info.end_direction = p->ainew.to_direction;
} else { } else {
p->ainew.path_info.end_tile_tl = p->ainew.to_tile; p->ainew.path_info.end_tile_tl = p->ainew.to_tile;
@ -847,9 +847,9 @@ static int AiNew_HowManyVehicles(Player *p) {
// Calculating tiles a day a vehicle moves is not easy.. this is how it must be done! // Calculating tiles a day a vehicle moves is not easy.. this is how it must be done!
tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16; tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16;
if (p->ainew.from_deliver) if (p->ainew.from_deliver)
max_cargo = DEREF_INDUSTRY(p->ainew.from_ic)->total_production[0]; max_cargo = GetIndustry(p->ainew.from_ic)->total_production[0];
else else
max_cargo = DEREF_INDUSTRY(p->ainew.to_ic)->total_production[0]; max_cargo = GetIndustry(p->ainew.to_ic)->total_production[0];
// This is because moving 60% is more than we can dream of! // This is because moving 60% is more than we can dream of!
max_cargo *= 0.6; max_cargo *= 0.6;

View File

@ -217,7 +217,7 @@ int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
const AirportFTAClass *Airport; const AirportFTAClass *Airport;
const TileIndexDiffC *cur_depot; const TileIndexDiffC *cur_depot;
byte i = 0; byte i = 0;
st = DEREF_STATION(_map2[tile]); st = GetStation(_map2[tile]);
Airport = GetAirport(st->airport_type); Airport = GetAirport(st->airport_type);
for (cur_depot = Airport->airport_depots; i != Airport->nof_depots; cur_depot++) { for (cur_depot = Airport->airport_depots; i != Airport->nof_depots; cur_depot++) {
if ((uint)(st->airport_tile + ToTileIndexDiff(*cur_depot)) == tile) { if ((uint)(st->airport_tile + ToTileIndexDiff(*cur_depot)) == tile) {
@ -311,7 +311,7 @@ int32 CmdSellAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner) || !CheckStoppedInHangar(v)) if (!CheckOwnership(v->owner) || !CheckStoppedInHangar(v))
return CMD_ERROR; return CMD_ERROR;
@ -332,7 +332,7 @@ int32 CmdStartStopAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *v; Vehicle *v;
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner)) if (!CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -357,7 +357,7 @@ int32 CmdSendAircraftToHangar(int x, int y, uint32 flags, uint32 p1, uint32 p2)
Vehicle *v; Vehicle *v;
Station *st; Station *st;
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner)) if (!CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -370,7 +370,7 @@ int32 CmdSendAircraftToHangar(int x, int y, uint32 flags, uint32 p1, uint32 p2)
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
} }
} else { } else {
st = DEREF_STATION(v->u.air.targetairport); st = GetStation(v->u.air.targetairport);
// If an airport doesn't have terminals (so no landing space for airports), // If an airport doesn't have terminals (so no landing space for airports),
// it surely doesn't have any hangars // 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)->nofterminals == 0)
@ -393,7 +393,7 @@ int32 CmdChangeAircraftServiceInt(int x, int y, uint32 flags, uint32 p1, uint32
{ {
Vehicle *v; Vehicle *v;
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner)) if (!CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -419,7 +419,7 @@ int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_RUN); SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_RUN);
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner) || (!CheckStoppedInHangar(v) && !(SkipStoppedInHangerCheck))) if (!CheckOwnership(v->owner) || (!CheckStoppedInHangar(v) && !(SkipStoppedInHangerCheck)))
return CMD_ERROR; return CMD_ERROR;
@ -481,7 +481,7 @@ static void CheckIfAircraftNeedsService(Vehicle *v)
if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr)) if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr))
return; return;
st = DEREF_STATION(v->current_order.station); st = GetStation(v->current_order.station);
// only goto depot if the target airport has terminals (eg. it is airport) // 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)->nofterminals != 0) {
// printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index); // printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index);
@ -720,7 +720,7 @@ static bool Aircraft_5(Vehicle *v)
uint dist; uint dist;
int x,y; int x,y;
st = DEREF_STATION(v->u.air.targetairport); st = GetStation(v->u.air.targetairport);
// prevent going to 0,0 if airport is deleted. // prevent going to 0,0 if airport is deleted.
{ {
@ -925,7 +925,7 @@ static void HandleCrashedAircraft(Vehicle *v)
v->u.air.crashed_counter++; v->u.air.crashed_counter++;
st = DEREF_STATION(v->u.air.targetairport); st = GetStation(v->u.air.targetairport);
// make aircraft crash down to the ground // make aircraft crash down to the ground
if ( st->airport_tile==0 && ((v->u.air.crashed_counter % 3) == 0) ) { if ( st->airport_tile==0 && ((v->u.air.crashed_counter % 3) == 0) ) {
@ -1112,7 +1112,7 @@ static void CrashAirplane(Vehicle *v)
v->cargo_count = 0; v->cargo_count = 0;
v->next->cargo_count = 0, v->next->cargo_count = 0,
st = DEREF_STATION(v->u.air.targetairport); st = GetStation(v->u.air.targetairport);
if(st->airport_tile==0) { if(st->airport_tile==0) {
newsitem = STR_PLANE_CRASH_OUT_OF_FUEL; newsitem = STR_PLANE_CRASH_OUT_OF_FUEL;
} else { } else {
@ -1135,7 +1135,7 @@ static void MaybeCrashAirplane(Vehicle *v)
uint16 prob; uint16 prob;
int i; int i;
st = DEREF_STATION(v->u.air.targetairport); st = GetStation(v->u.air.targetairport);
//FIXME -- MaybeCrashAirplane -> increase crashing chances of very modern airplanes on smaller than AT_METROPOLITAN airports //FIXME -- MaybeCrashAirplane -> increase crashing chances of very modern airplanes on smaller than AT_METROPOLITAN airports
prob = 0x10000 / 1500; prob = 0x10000 / 1500;
@ -1164,7 +1164,7 @@ static void AircraftEntersTerminal(Vehicle *v)
if (v->current_order.type == OT_GOTO_DEPOT) if (v->current_order.type == OT_GOTO_DEPOT)
return; return;
st = DEREF_STATION(v->u.air.targetairport); st = GetStation(v->u.air.targetairport);
v->last_station_visited = v->u.air.targetairport; v->last_station_visited = v->u.air.targetairport;
/* Check if station was ever visited before */ /* Check if station was ever visited before */
@ -1253,7 +1253,7 @@ static void AircraftNextAirportPos_and_Order(Vehicle *v)
v->current_order.type == OT_GOTO_DEPOT) v->current_order.type == OT_GOTO_DEPOT)
v->u.air.targetairport = v->current_order.station; v->u.air.targetairport = v->current_order.station;
st = DEREF_STATION(v->u.air.targetairport); st = GetStation(v->u.air.targetairport);
Airport = GetAirport(st->airport_type); Airport = GetAirport(st->airport_type);
v->u.air.pos = v->u.air.previous_pos = Airport->entry_point; v->u.air.pos = v->u.air.previous_pos = Airport->entry_point;
} }
@ -1423,7 +1423,7 @@ static void AircraftEventHandler_Flying(Vehicle *v, const AirportFTAClass *Airpo
AirportFTA *current; AirportFTA *current;
uint16 tcur_speed, tsubspeed; uint16 tcur_speed, tsubspeed;
st = DEREF_STATION(v->u.air.targetairport); st = GetStation(v->u.air.targetairport);
// flying device is accepted at this station // flying device is accepted at this station
// small airport --> no helicopters (AIRCRAFT_ONLY) // small airport --> no helicopters (AIRCRAFT_ONLY)
// all other airports --> all types of flying devices (ALL) // all other airports --> all types of flying devices (ALL)
@ -1537,7 +1537,7 @@ static void AirportClearBlock(Vehicle *v, const AirportFTAClass *Airport)
Station *st; Station *st;
// we have left the previous block, and entered the new one. Free the previous block // we have left the previous block, and entered the new one. Free the previous block
if (Airport->layout[v->u.air.previous_pos].block != Airport->layout[v->u.air.pos].block) { if (Airport->layout[v->u.air.previous_pos].block != Airport->layout[v->u.air.pos].block) {
st = DEREF_STATION(v->u.air.targetairport); st = GetStation(v->u.air.targetairport);
CLRBITS(st->airport_flags, Airport->layout[v->u.air.previous_pos].block); CLRBITS(st->airport_flags, Airport->layout[v->u.air.previous_pos].block);
} }
} }
@ -1613,7 +1613,7 @@ static bool AirportHasBlock(Vehicle *v, AirportFTA *current_pos, const AirportFT
// same block, then of course we can move // same block, then of course we can move
if (Airport->layout[current_pos->position].block != next->block) { if (Airport->layout[current_pos->position].block != next->block) {
airport_flags = next->block; airport_flags = next->block;
st = DEREF_STATION(v->u.air.targetairport); st = GetStation(v->u.air.targetairport);
// check additional possible extra blocks // check additional possible extra blocks
if (current_pos != reference && current_pos->block != NOTHING_block) { if (current_pos != reference && current_pos->block != NOTHING_block) {
airport_flags |= current_pos->block; airport_flags |= current_pos->block;
@ -1640,7 +1640,7 @@ static bool AirportSetBlocks(Vehicle *v, AirportFTA *current_pos, const AirportF
// if the next position is in another block, check it and wait until it is free // if the next position is in another block, check it and wait until it is free
if (Airport->layout[current_pos->position].block != next->block) { if (Airport->layout[current_pos->position].block != next->block) {
airport_flags = next->block; airport_flags = next->block;
st = DEREF_STATION(v->u.air.targetairport); st = GetStation(v->u.air.targetairport);
//search for all all elements in the list with the same state, and blocks != N //search for all all elements in the list with the same state, and blocks != N
// this means more blocks should be checked/set // this means more blocks should be checked/set
current = current_pos; current = current_pos;
@ -1672,7 +1672,7 @@ static bool AirportSetBlocks(Vehicle *v, AirportFTA *current_pos, const AirportF
static bool FreeTerminal(Vehicle *v, byte i, byte last_terminal) static bool FreeTerminal(Vehicle *v, byte i, byte last_terminal)
{ {
Station *st = DEREF_STATION(v->u.air.targetairport); Station *st = GetStation(v->u.air.targetairport);
for (; i < last_terminal; i++) { for (; i < last_terminal; i++) {
if (!HASBIT(st->airport_flags, i)) { if (!HASBIT(st->airport_flags, i)) {
// TERMINAL# HELIPAD# // TERMINAL# HELIPAD#
@ -1701,7 +1701,7 @@ static bool AirportFindFreeTerminal(Vehicle *v, const AirportFTAClass *Airport)
fails, then attempt fails and plane waits fails, then attempt fails and plane waits
*/ */
if (Airport->nofterminalgroups > 1) { if (Airport->nofterminalgroups > 1) {
st = DEREF_STATION(v->u.air.targetairport); st = GetStation(v->u.air.targetairport);
nofterminalspergroup = Airport->nofterminals / Airport->nofterminalgroups; nofterminalspergroup = Airport->nofterminals / Airport->nofterminalgroups;
temp = Airport->layout[v->u.air.pos].next_in_chain; temp = Airport->layout[v->u.air.pos].next_in_chain;
while (temp != NULL) { while (temp != NULL) {
@ -1734,7 +1734,7 @@ static bool AirportFindFreeHelipad(Vehicle *v, const AirportFTAClass *Airport)
// if there are more helicoptergroups, pick one, just as in AirportFindFreeTerminal() // if there are more helicoptergroups, pick one, just as in AirportFindFreeTerminal()
if (Airport->nofhelipadgroups > 1) { if (Airport->nofhelipadgroups > 1) {
st = DEREF_STATION(v->u.air.targetairport); st = GetStation(v->u.air.targetairport);
nofhelipadspergroup = Airport->nofhelipads / Airport->nofhelipadgroups; nofhelipadspergroup = Airport->nofhelipads / Airport->nofhelipadgroups;
temp = Airport->layout[v->u.air.pos].next_in_chain; temp = Airport->layout[v->u.air.pos].next_in_chain;
while (temp != NULL) { while (temp != NULL) {
@ -1787,7 +1787,7 @@ static void AircraftEventHandler(Vehicle *v, int loop)
// pass the right airport structure to the functions // pass the right airport structure to the functions
// DEREF_STATION gets target airport (Station *st), its type is passed to GetAirport // DEREF_STATION gets target airport (Station *st), its type is passed to GetAirport
// that returns the correct layout depending on type // that returns the correct layout depending on type
AirportGoToNextPosition(v, GetAirport(DEREF_STATION(v->u.air.targetairport)->airport_type)); AirportGoToNextPosition(v, GetAirport(GetStation(v->u.air.targetairport)->airport_type));
} }
void Aircraft_Tick(Vehicle *v) void Aircraft_Tick(Vehicle *v)

View File

@ -51,7 +51,7 @@ void CcBuildAircraft(bool success, uint tile, uint32 p1, uint32 p2)
Vehicle *v; Vehicle *v;
if (success) { if (success) {
v = &_vehicles[_new_aircraft_id]; v = GetVehicle(_new_aircraft_id);
if (v->tile == _backup_orders_tile) { if (v->tile == _backup_orders_tile) {
_backup_orders_tile = 0; _backup_orders_tile = 0;
RestoreVehicleOrders(v, _backup_orders_data); RestoreVehicleOrders(v, _backup_orders_data);
@ -217,7 +217,7 @@ static void AircraftRefitWndProc(Window *w, WindowEvent *e)
{ {
switch(e->event) { switch(e->event) {
case WE_PAINT: { case WE_PAINT: {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
const byte *b; const byte *b;
int sel; int sel;
int x,y; int x,y;
@ -296,7 +296,7 @@ static void AircraftRefitWndProc(Window *w, WindowEvent *e)
} break; } break;
case 4: /* refit button */ case 4: /* refit button */
if (WP(w,refit_d).cargo != 0xFF) { if (WP(w,refit_d).cargo != 0xFF) {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_AIRCRAFT | CMD_MSG(STR_A042_CAN_T_REFIT_AIRCRAFT))) if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_AIRCRAFT | CMD_MSG(STR_A042_CAN_T_REFIT_AIRCRAFT)))
DeleteWindow(w); DeleteWindow(w);
} }
@ -339,7 +339,7 @@ static void ShowAircraftRefitWindow(Vehicle *v)
static void AircraftDetailsWndProc(Window *w, WindowEvent *e) static void AircraftDetailsWndProc(Window *w, WindowEvent *e)
{ {
int mod; int mod;
Vehicle *v = &_vehicles[w->window_number], *u; Vehicle *v = GetVehicle(w->window_number), *u;
switch(e->event) { switch(e->event) {
case WE_PAINT: case WE_PAINT:
@ -534,7 +534,7 @@ static void AircraftViewWndProc(Window *w, WindowEvent *e)
{ {
switch(e->event) { switch(e->event) {
case WE_PAINT: { case WE_PAINT: {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
uint32 disabled = 1<<8; uint32 disabled = 1<<8;
StringID str; StringID str;
@ -595,7 +595,7 @@ static void AircraftViewWndProc(Window *w, WindowEvent *e)
} break; } break;
case WE_CLICK: { case WE_CLICK: {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
switch(e->click.widget) { switch(e->click.widget) {
case 5: /* start stop */ case 5: /* start stop */
@ -832,7 +832,7 @@ static void AircraftDepotWndProc(Window *w, WindowEvent *e)
HandleButtonClick(w, 5); HandleButtonClick(w, 5);
v = &_vehicles[WP(w,traindepot_d).sel]; v = GetVehicle(WP(w,traindepot_d).sel);
WP(w,traindepot_d).sel = INVALID_VEHICLE; WP(w,traindepot_d).sel = INVALID_VEHICLE;
_backup_orders_tile = v->tile; _backup_orders_tile = v->tile;
@ -979,7 +979,7 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
w->widget[1].unkA = STR_A009_AIRCRAFT; w->widget[1].unkA = STR_A009_AIRCRAFT;
} else { } else {
/* Station Name -- (###) Aircraft */ /* Station Name -- (###) Aircraft */
SetDParam(0, DEREF_STATION(station)->index); SetDParam(0, GetStation(station)->index);
SetDParam(1, w->vscroll.count); SetDParam(1, w->vscroll.count);
w->widget[1].unkA = STR_SCHEDULED_AIRCRAFT; w->widget[1].unkA = STR_SCHEDULED_AIRCRAFT;
} }
@ -993,7 +993,7 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length); max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length);
for (i = w->vscroll.pos; i < max; ++i) { for (i = w->vscroll.pos; i < max; ++i) {
Vehicle *v = DEREF_VEHICLE(vl->sort_list[i].index); Vehicle *v = GetVehicle(vl->sort_list[i].index);
StringID str; StringID str;
assert(v->type == VEH_Aircraft && v->subtype <= 2); assert(v->type == VEH_Aircraft && v->subtype <= 2);
@ -1047,7 +1047,7 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
if (id_v >= vl->list_length) return; // click out of list bound if (id_v >= vl->list_length) return; // click out of list bound
v = DEREF_VEHICLE(vl->sort_list[id_v].index); v = GetVehicle(vl->sort_list[id_v].index);
assert(v->type == VEH_Aircraft && v->subtype <= 2); assert(v->type == VEH_Aircraft && v->subtype <= 2);

View File

@ -193,7 +193,7 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
IS_BYTE_INSIDE(_map5[tile], 8, 0x43) && IS_BYTE_INSIDE(_map5[tile], 8, 0x43) &&
IS_HUMAN_PLAYER(_map_owner[tile])) { IS_HUMAN_PLAYER(_map_owner[tile])) {
st = DEREF_STATION(_map2[tile]); st = GetStation(_map2[tile]);
CLRBITS(st->airport_flags, RUNWAY_IN_block); CLRBITS(st->airport_flags, RUNWAY_IN_block);
} }
@ -235,7 +235,7 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
IS_BYTE_INSIDE(_map5[tile], 8, 0x43) && IS_BYTE_INSIDE(_map5[tile], 8, 0x43) &&
IS_HUMAN_PLAYER(_map_owner[tile])) { IS_HUMAN_PLAYER(_map_owner[tile])) {
st = DEREF_STATION(_map2[tile]); st = GetStation(_map2[tile]);
SETBITS(st->airport_flags, RUNWAY_IN_block); SETBITS(st->airport_flags, RUNWAY_IN_block);
} }
} }
@ -278,7 +278,7 @@ static void DisasterTick_UFO(Vehicle *v)
DeleteDisasterVeh(v); DeleteDisasterVeh(v);
} else { } else {
// target a vehicle // target a vehicle
u = &_vehicles[v->dest_tile]; u = GetVehicle(v->dest_tile);
if (u->type != VEH_Road) { if (u->type != VEH_Road) {
DeleteDisasterVeh(v); DeleteDisasterVeh(v);
return; return;
@ -323,10 +323,9 @@ static void DisasterTick_UFO(Vehicle *v)
static void DestructIndustry(Industry *i) static void DestructIndustry(Industry *i)
{ {
uint tile; uint tile;
byte index = i - _industries;
for(tile=0; tile != MapSize(); tile++) { for(tile=0; tile != MapSize(); tile++) {
if (IS_TILETYPE(tile, MP_INDUSTRY) && _map2[tile] == index) { if (IS_TILETYPE(tile, MP_INDUSTRY) && _map2[tile] == i->index) {
_map_owner[tile] = 0; _map_owner[tile] = 0;
MarkTileDirtyByTile(tile); MarkTileDirtyByTile(tile);
} }
@ -352,7 +351,7 @@ static void DisasterTick_2(Vehicle *v)
if (v->current_order.station == 2) { if (v->current_order.station == 2) {
if (!(v->tick_counter&3)) { if (!(v->tick_counter&3)) {
Industry *i = DEREF_INDUSTRY(v->dest_tile); Industry *i = GetIndustry(v->dest_tile);
int x = GET_TILE_X(i->xy)*16; int x = GET_TILE_X(i->xy)*16;
int y = GET_TILE_Y(i->xy)*16; int y = GET_TILE_Y(i->xy)*16;
uint32 r = Random(); uint32 r = Random();
@ -373,7 +372,7 @@ static void DisasterTick_2(Vehicle *v)
v->current_order.station = 2; v->current_order.station = 2;
v->age = 0; v->age = 0;
i = DEREF_INDUSTRY(v->dest_tile); i = GetIndustry(v->dest_tile);
DestructIndustry(i); DestructIndustry(i);
SetDParam(0, i->town->index); SetDParam(0, i->town->index);
@ -397,7 +396,7 @@ static void DisasterTick_2(Vehicle *v)
v->dest_tile = ind = _map2[tile]; v->dest_tile = ind = _map2[tile];
if (DEREF_INDUSTRY(ind)->type == IT_OIL_REFINERY) { if (GetIndustry(ind)->type == IT_OIL_REFINERY) {
v->current_order.station = 1; v->current_order.station = 1;
v->age = 0; v->age = 0;
} }
@ -423,7 +422,7 @@ static void DisasterTick_3(Vehicle *v)
if (v->current_order.station == 2) { if (v->current_order.station == 2) {
if (!(v->tick_counter&3)) { if (!(v->tick_counter&3)) {
Industry *i = DEREF_INDUSTRY(v->dest_tile); Industry *i = GetIndustry(v->dest_tile);
int x = GET_TILE_X(i->xy)*16; int x = GET_TILE_X(i->xy)*16;
int y = GET_TILE_Y(i->xy)*16; int y = GET_TILE_Y(i->xy)*16;
uint32 r = Random(); uint32 r = Random();
@ -444,7 +443,7 @@ static void DisasterTick_3(Vehicle *v)
v->current_order.station = 2; v->current_order.station = 2;
v->age = 0; v->age = 0;
i = DEREF_INDUSTRY(v->dest_tile); i = GetIndustry(v->dest_tile);
DestructIndustry(i); DestructIndustry(i);
SetDParam(0, i->town->index); SetDParam(0, i->town->index);
@ -468,7 +467,7 @@ static void DisasterTick_3(Vehicle *v)
v->dest_tile = ind = _map2[tile]; v->dest_tile = ind = _map2[tile];
if (DEREF_INDUSTRY(ind)->type == IT_FACTORY) { if (GetIndustry(ind)->type == IT_FACTORY) {
v->current_order.station = 1; v->current_order.station = 1;
v->age = 0; v->age = 0;
} }
@ -600,7 +599,7 @@ static void DisasterTick_4b(Vehicle *v)
} }
if (v->current_order.station == 0) { if (v->current_order.station == 0) {
u = &_vehicles[v->u.disaster.unk2]; u = GetVehicle(v->u.disaster.unk2);
if (abs(v->x_pos - u->x_pos) > 16) if (abs(v->x_pos - u->x_pos) > 16)
return; return;
v->current_order.station = 1; v->current_order.station = 1;
@ -701,18 +700,17 @@ static void Disaster0_Init()
if (v == NULL) if (v == NULL)
return; return;
for(st=_stations;;) { /* Pick a random place, unless we find
a small airport */
x = (GET_TILE_X(Random())) * 16 + 8;
FOR_ALL_STATIONS(st) {
if (st->xy && st->airport_tile != 0 && if (st->xy && st->airport_tile != 0 &&
st->airport_type <= 1 && st->airport_type <= 1 &&
IS_HUMAN_PLAYER(st->owner)) { IS_HUMAN_PLAYER(st->owner)) {
x = (GET_TILE_X(st->xy) + 2) * 16; x = (GET_TILE_X(st->xy) + 2) * 16;
break; break;
} }
if (++st == endof(_stations)) {
x = (GET_TILE_X(Random())) * 16 + 8;
break;
}
} }
InitializeDisasterVehicle(v, x, 0, 135, 3, 0); InitializeDisasterVehicle(v, x, 0, 135, 3, 0);
@ -721,7 +719,7 @@ static void Disaster0_Init()
u = ForceAllocateSpecialVehicle(); u = ForceAllocateSpecialVehicle();
if (u != NULL) { if (u != NULL) {
v->next = u; v->next = u;
InitializeDisasterVehicle(u,x,0,0,3,1); InitializeDisasterVehicle(u, x, 0, 0, 3, 1);
u->vehstatus |= VS_DISASTER; u->vehstatus |= VS_DISASTER;
} }
} }

View File

@ -270,7 +270,7 @@ void ChangeOwnershipOfPlayerItems(byte old_player, byte new_player)
for(s=_subsidies; s != endof(_subsidies); s++) { for(s=_subsidies; s != endof(_subsidies); s++) {
if (s->cargo_type != 0xff && s->age >= 12) { if (s->cargo_type != 0xff && s->age >= 12) {
Station *st = DEREF_STATION(s->to); Station *st = GetStation(s->to);
if (st->owner == old_player) if (st->owner == old_player)
s->cargo_type = 0xff; s->cargo_type = 0xff;
} }
@ -798,7 +798,7 @@ Pair SetupSubsidyDecodeParam(Subsidy *s, bool mode)
if (s->age < 12) { if (s->age < 12) {
if (!(s->cargo_type == CT_PASSENGERS || s->cargo_type == CT_MAIL)) { if (!(s->cargo_type == CT_PASSENGERS || s->cargo_type == CT_MAIL)) {
SetDParam(1, STR_2029); SetDParam(1, STR_2029);
i = DEREF_INDUSTRY(s->from); i = GetIndustry(s->from);
tile = i->xy; tile = i->xy;
SetDParam(2, i->town->townnametype); SetDParam(2, i->town->townnametype);
SetDParam(3, i->town->townnameparts); SetDParam(3, i->town->townnameparts);
@ -807,34 +807,34 @@ Pair SetupSubsidyDecodeParam(Subsidy *s, bool mode)
if (s->cargo_type != CT_GOODS && s->cargo_type != CT_FOOD) { if (s->cargo_type != CT_GOODS && s->cargo_type != CT_FOOD) {
SetDParam(5, STR_2029); SetDParam(5, STR_2029);
i = DEREF_INDUSTRY(s->to); i = GetIndustry(s->to);
tile2 = i->xy; tile2 = i->xy;
SetDParam(8, i->type + STR_4802_COAL_MINE); SetDParam(8, i->type + STR_4802_COAL_MINE);
SetDParam(6, i->town->townnametype); SetDParam(6, i->town->townnametype);
SetDParam(7, i->town->townnameparts); SetDParam(7, i->town->townnameparts);
} else { } else {
t = DEREF_TOWN(s->to); t = GetTown(s->to);
tile2 = t->xy; tile2 = t->xy;
SetDParam(5, t->townnametype); SetDParam(5, t->townnametype);
SetDParam(6, t->townnameparts); SetDParam(6, t->townnameparts);
} }
} else { } else {
t = DEREF_TOWN(s->from); t = GetTown(s->from);
tile = t->xy; tile = t->xy;
SetDParam(1, t->townnametype); SetDParam(1, t->townnametype);
SetDParam(2, t->townnameparts); SetDParam(2, t->townnameparts);
t = DEREF_TOWN(s->to); t = GetTown(s->to);
tile2 = t->xy; tile2 = t->xy;
SetDParam(3, t->townnametype); SetDParam(3, t->townnametype);
SetDParam(4, t->townnameparts); SetDParam(4, t->townnameparts);
} }
} else { } else {
st = DEREF_STATION(s->from); st = GetStation(s->from);
tile = st->xy; tile = st->xy;
SetDParam(1, st->index); SetDParam(1, st->index);
st = DEREF_STATION(s->to); st = GetStation(s->to);
tile2 = st->xy; tile2 = st->xy;
SetDParam(2, st->index); SetDParam(2, st->index);
} }
@ -888,11 +888,11 @@ static void FindSubsidyPassengerRoute(FoundRoute *fr)
fr->distance = (uint)-1; fr->distance = (uint)-1;
fr->from = from = DEREF_TOWN(RandomRange(_total_towns)); fr->from = from = GetTown(RandomRange(_total_towns));
if (from->xy == 0 || from->population < 400) if (from->xy == 0 || from->population < 400)
return; return;
fr->to = to = DEREF_TOWN(RandomRange(_total_towns)); fr->to = to = GetTown(RandomRange(_total_towns));
if (from==to || to->xy == 0 || to->population < 400 || to->pct_pass_transported > 42) if (from==to || to->xy == 0 || to->population < 400 || to->pct_pass_transported > 42)
return; return;
@ -907,7 +907,7 @@ static void FindSubsidyCargoRoute(FoundRoute *fr)
fr->distance = (uint)-1; fr->distance = (uint)-1;
fr->from = i = DEREF_INDUSTRY(RandomRange(_total_industries)); fr->from = i = GetIndustry(RandomRange(_total_industries));
if (i->xy == 0) if (i->xy == 0)
return; return;
@ -932,7 +932,7 @@ static void FindSubsidyCargoRoute(FoundRoute *fr)
if (cargo == CT_GOODS || cargo == CT_FOOD) { if (cargo == CT_GOODS || cargo == CT_FOOD) {
// The destination is a town // The destination is a town
Town *t = DEREF_TOWN(RandomRange(_total_towns)); Town *t = GetTown(RandomRange(_total_towns));
// Only want big towns // Only want big towns
if (t->xy == 0 || t->population < 900) if (t->xy == 0 || t->population < 900)
@ -941,7 +941,7 @@ static void FindSubsidyCargoRoute(FoundRoute *fr)
fr->to = t; fr->to = t;
} else { } else {
// The destination is an industry // The destination is an industry
Industry *i2 = DEREF_INDUSTRY(RandomRange(_total_industries)); Industry *i2 = GetIndustry(RandomRange(_total_industries));
// The industry must accept the cargo // The industry must accept the cargo
if (i == i2 || i2->xy == 0 || if (i == i2 || i2->xy == 0 ||
@ -1008,7 +1008,7 @@ static void SubsidyMonthlyHandler()
s->cargo_type = 0xFF; s->cargo_type = 0xFF;
modified = true; modified = true;
} else if (s->age == 2*12-1) { } else if (s->age == 2*12-1) {
st = DEREF_STATION(s->to); st = GetStation(s->to);
if (st->owner == _local_player) { if (st->owner == _local_player) {
pair = SetupSubsidyDecodeParam(s, 1); pair = SetupSubsidyDecodeParam(s, 1);
AddNewsItem(STR_202F_SUBSIDY_WITHDRAWN_SERVICE, NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_SUBSIDIES, 0), pair.a, pair.b); AddNewsItem(STR_202F_SUBSIDY_WITHDRAWN_SERVICE, NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_SUBSIDIES, 0), pair.a, pair.b);
@ -1041,8 +1041,8 @@ static void SubsidyMonthlyHandler()
FindSubsidyCargoRoute(&fr); FindSubsidyCargoRoute(&fr);
if (fr.distance <= 70) { if (fr.distance <= 70) {
s->cargo_type = fr.cargo; s->cargo_type = fr.cargo;
s->from = (Industry*)fr.from - _industries; s->from = ((Industry*)fr.from)->index;
s->to = (fr.cargo == CT_GOODS || fr.cargo == CT_FOOD) ? ((Town*)fr.to)->index : (Industry*)fr.to - _industries; s->to = (fr.cargo == CT_GOODS || fr.cargo == CT_FOOD) ? ((Town*)fr.to)->index : ((Industry*)fr.to)->index;
add_subsidy: add_subsidy:
if (!CheckSubsidyDuplicate(s)) { if (!CheckSubsidyDuplicate(s)) {
s->age = 0; s->age = 0;
@ -1167,18 +1167,18 @@ static bool CheckSubsidised(Station *from, Station *to, byte cargo_type)
/* Check distance from source */ /* Check distance from source */
if (cargo_type == CT_PASSENGERS || cargo_type == CT_MAIL) { if (cargo_type == CT_PASSENGERS || cargo_type == CT_MAIL) {
xy = DEREF_TOWN(s->from)->xy; xy = GetTown(s->from)->xy;
} else { } else {
xy = (DEREF_INDUSTRY(s->from))->xy; xy = (GetIndustry(s->from))->xy;
} }
if (GetTileDist1D(xy, from->xy) > 9) if (GetTileDist1D(xy, from->xy) > 9)
continue; continue;
/* Check distance from dest */ /* Check distance from dest */
if (cargo_type == CT_PASSENGERS || cargo_type == CT_MAIL || cargo_type == CT_GOODS || cargo_type == CT_FOOD) { if (cargo_type == CT_PASSENGERS || cargo_type == CT_MAIL || cargo_type == CT_GOODS || cargo_type == CT_FOOD) {
xy = DEREF_TOWN(s->to)->xy; xy = GetTown(s->to)->xy;
} else { } else {
xy = (DEREF_INDUSTRY(s->to))->xy; xy = (GetIndustry(s->to))->xy;
} }
if (GetTileDist1D(xy, to->xy) > 9) if (GetTileDist1D(xy, to->xy) > 9)
@ -1224,8 +1224,8 @@ static int32 DeliverGoods(int num_pieces, byte cargo_type, byte source, byte des
} }
// Get station pointers. // Get station pointers.
s_from = DEREF_STATION(source); s_from = GetStation(source);
s_to = DEREF_STATION(dest); s_to = GetStation(dest);
// Check if a subsidy applies. // Check if a subsidy applies.
subsidised = CheckSubsidised(s_from, s_to, cargo_type); subsidised = CheckSubsidised(s_from, s_to, cargo_type);
@ -1349,7 +1349,7 @@ int LoadUnloadVehicle(Vehicle *v)
old_player = _current_player; old_player = _current_player;
_current_player = v->owner; _current_player = v->owner;
st = DEREF_STATION(last_visited = v->last_station_visited); st = GetStation(last_visited = v->last_station_visited);
for (; v != NULL; v = v->next) { for (; v != NULL; v = v->next) {
if (v->cargo_cap == 0) continue; if (v->cargo_cap == 0) continue;

View File

@ -737,17 +737,22 @@ static void NewVehicleAvailable(Engine *e)
// prevent that player from getting future intro periods for a while. // prevent that player from getting future intro periods for a while.
if (e->flags&ENGINE_INTRODUCING) { if (e->flags&ENGINE_INTRODUCING) {
FOR_ALL_PLAYERS(p) { FOR_ALL_PLAYERS(p) {
uint block_preview = p->block_preview;
if (!HASBIT(e->player_avail,p->index)) if (!HASBIT(e->player_avail,p->index))
continue; continue;
for(v=_vehicles;;) { /* We assume the user did NOT build it.. prove me wrong ;) */
p->block_preview = 20;
FOR_ALL_VEHICLES(v) {
if (v->type == VEH_Train || v->type == VEH_Road || v->type == VEH_Ship || if (v->type == VEH_Train || v->type == VEH_Road || v->type == VEH_Ship ||
(v->type == VEH_Aircraft && v->subtype <= 2)) { (v->type == VEH_Aircraft && v->subtype <= 2)) {
if (v->owner == p->index && v->engine_type == index) break; if (v->owner == p->index && v->engine_type == index) {
} /* The user did prove me wrong, so restore old value */
if (++v == endof(_vehicles)) { p->block_preview = block_preview;
p->block_preview = 20; break;
break; }
} }
} }
} }

View File

@ -23,12 +23,25 @@ struct Industry {
byte color_map; byte color_map;
byte last_prod_year; byte last_prod_year;
byte was_cargo_delivered; byte was_cargo_delivered;
uint16 index;
}; };
VARDEF int _total_industries; // For the AI: the amount of industries active VARDEF int _total_industries; // For the AI: the amount of industries active
VARDEF Industry _industries[90]; VARDEF Industry _industries[90];
#define DEREF_INDUSTRY(i) (&_industries[i]) VARDEF uint _industries_size;
#define FOR_ALL_INDUSTRIES(i) for(i = _industries; i != endof(_industries); i++)
VARDEF uint16 *_industry_sort;
static inline Industry *GetIndustry(uint index)
{
assert(index < _industries_size);
return &_industries[index];
}
#define FOR_ALL_INDUSTRIES(i) for(i = _industries; i != &_industries[_industries_size]; i++)
VARDEF bool _industry_sort_dirty; VARDEF bool _industry_sort_dirty;
void DeleteIndustry(Industry *is); void DeleteIndustry(Industry *is);

View File

@ -282,7 +282,7 @@ static void DrawTile_Industry(TileInfo *ti)
uint32 image, ormod; uint32 image, ormod;
/* Pointer to industry */ /* Pointer to industry */
ind = DEREF_INDUSTRY(_map2[ti->tile]); ind = GetIndustry(_map2[ti->tile]);
ormod = (ind->color_map+0x307)<<16; ormod = (ind->color_map+0x307)<<16;
/* Retrieve pointer to the draw industry tile struct */ /* Retrieve pointer to the draw industry tile struct */
@ -358,7 +358,7 @@ static void GetAcceptedCargo_Industry(uint tile, AcceptedCargo ac)
static void GetTileDesc_Industry(uint tile, TileDesc *td) static void GetTileDesc_Industry(uint tile, TileDesc *td)
{ {
Industry *i = DEREF_INDUSTRY(_map2[tile]); Industry *i = GetIndustry(_map2[tile]);
td->owner = i->owner; td->owner = i->owner;
td->str = STR_4802_COAL_MINE + i->type; td->str = STR_4802_COAL_MINE + i->type;
@ -370,7 +370,7 @@ static void GetTileDesc_Industry(uint tile, TileDesc *td)
static int32 ClearTile_Industry(uint tile, byte flags) static int32 ClearTile_Industry(uint tile, byte flags)
{ {
Industry *i = DEREF_INDUSTRY(_map2[tile]); Industry *i = GetIndustry(_map2[tile]);
/* * water can destroy industries /* * water can destroy industries
* in editor you can bulldoze industries * in editor you can bulldoze industries
@ -395,7 +395,7 @@ static int32 ClearTile_Industry(uint tile, byte flags)
int32 CmdDestroyIndustry(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 CmdDestroyIndustry(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
uint tile = TILE_FROM_XY(x,y); uint tile = TILE_FROM_XY(x,y);
Industry *i = DEREF_INDUSTRY((uint16)p1); Industry *i = GetIndustry((uint16)p1);
Town *t = ClosestTownFromTile(tile, (uint)-1); // find closest town to penaltize (ALWAYS penaltize) Town *t = ClosestTownFromTile(tile, (uint)-1); // find closest town to penaltize (ALWAYS penaltize)
SET_EXPENSES_TYPE(EXPENSES_OTHER); SET_EXPENSES_TYPE(EXPENSES_OTHER);
@ -430,7 +430,7 @@ static void TransportIndustryGoods(uint tile)
uint cw, am; uint cw, am;
byte m5; byte m5;
i = DEREF_INDUSTRY(_map2[tile]); i = GetIndustry(_map2[tile]);
type = i->type; type = i->type;
cw = min(i->cargo_waiting[0], 255); cw = min(i->cargo_waiting[0], 255);
@ -784,7 +784,7 @@ static void TileLoop_Industry(uint tile)
case 143: { case 143: {
Industry *i = DEREF_INDUSTRY(_map2[tile]); Industry *i = GetIndustry(_map2[tile]);
if (i->was_cargo_delivered) { if (i->was_cargo_delivered) {
i->was_cargo_delivered = false; i->was_cargo_delivered = false;
if ((_map3_hi[tile]|_map3_lo[tile]) != 0) if ((_map3_hi[tile]|_map3_lo[tile]) != 0)
@ -823,7 +823,7 @@ static uint32 GetTileTrackStatus_Industry(uint tile, TransportType mode)
static void GetProducedCargo_Industry(uint tile, byte *b) static void GetProducedCargo_Industry(uint tile, byte *b)
{ {
Industry *i = DEREF_INDUSTRY(_map2[tile]); Industry *i = GetIndustry(_map2[tile]);
b[0] = i->produced_cargo[0]; b[0] = i->produced_cargo[0];
b[1] = i->produced_cargo[1]; b[1] = i->produced_cargo[1];
} }
@ -835,22 +835,20 @@ static void ChangeTileOwner_Industry(uint tile, byte old_player, byte new_player
void DeleteIndustry(Industry *i) void DeleteIndustry(Industry *i)
{ {
int index = i - _industries; BEGIN_TILE_LOOP(tile_cur, i->width, i->height, i->xy);
BEGIN_TILE_LOOP(tile_cur, i->width, i->height, i->xy);
if (IS_TILETYPE(tile_cur, MP_INDUSTRY)) { if (IS_TILETYPE(tile_cur, MP_INDUSTRY)) {
if (_map2[tile_cur] == (uint16)index) { if (_map2[tile_cur] == i->index) {
DoClearSquare(tile_cur); DoClearSquare(tile_cur);
} }
} else if (IS_TILETYPE(tile_cur, MP_STATION) && _map5[tile_cur] == 0x4B) { } else if (IS_TILETYPE(tile_cur, MP_STATION) && _map5[tile_cur] == 0x4B) {
DeleteOilRig(tile_cur); DeleteOilRig(tile_cur);
} }
END_TILE_LOOP(tile_cur, i->width, i->height, i->xy); END_TILE_LOOP(tile_cur, i->width, i->height, i->xy);
i->xy = 0; i->xy = 0;
_industry_sort_dirty = true; _industry_sort_dirty = true;
DeleteSubsidyWithIndustry(index); DeleteSubsidyWithIndustry(i->index);
DeleteWindowById(WC_INDUSTRY_VIEW, index); DeleteWindowById(WC_INDUSTRY_VIEW, i->index);
InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0); InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0);
} }
@ -1400,8 +1398,9 @@ static Industry *AllocateIndustry()
FOR_ALL_INDUSTRIES(i) { FOR_ALL_INDUSTRIES(i) {
if (i->xy == 0) { if (i->xy == 0) {
int index = i - _industries; if (i->index > _total_industries)
if (index > _total_industries) _total_industries = index; _total_industries = i->index;
return i; return i;
} }
} }
@ -1475,7 +1474,7 @@ static void DoCreateNewIndustry(Industry *i, uint tile, int type, const Industry
_map_type_and_height[cur_tile] = (_map_type_and_height[cur_tile]&~0xF0) | (MP_INDUSTRY<<4); _map_type_and_height[cur_tile] = (_map_type_and_height[cur_tile]&~0xF0) | (MP_INDUSTRY<<4);
_map5[cur_tile] = it->map5; _map5[cur_tile] = it->map5;
_map2[cur_tile] = i - _industries; _map2[cur_tile] = i->index;
_map_owner[cur_tile] = _generating_world ? 0x1E : 0; /* maturity */ _map_owner[cur_tile] = _generating_world ? 0x1E : 0; /* maturity */
} }
} while ((++it)->ti.x != -0x80); } while ((++it)->ti.x != -0x80);
@ -1711,7 +1710,7 @@ static void UpdateIndustryStatistics(Industry *i)
if ( i->produced_cargo[0] != 0xFF || i->produced_cargo[1] != 0xFF ) if ( i->produced_cargo[0] != 0xFF || i->produced_cargo[1] != 0xFF )
InvalidateWindow(WC_INDUSTRY_VIEW, i - _industries); InvalidateWindow(WC_INDUSTRY_VIEW, i->index);
if (i->prod_level == 0) if (i->prod_level == 0)
DeleteIndustry(i); DeleteIndustry(i);
@ -1819,7 +1818,7 @@ void IndustryMonthlyLoop()
UpdateIndustryStatistics(i); UpdateIndustryStatistics(i);
} }
i = DEREF_INDUSTRY(RandomRange(lengthof(_industries))); i = GetIndustry(RandomRange(_industries_size));
if (i->xy == 0) { if (i->xy == 0) {
uint32 r; uint32 r;
@ -1839,7 +1838,15 @@ void IndustryMonthlyLoop()
void InitializeIndustries() void InitializeIndustries()
{ {
memset(_industries, 0, sizeof(_industries)); Industry *i;
int j;
memset(_industries, 0, sizeof(_industries[0]) * _industries_size);
j = 0;
FOR_ALL_INDUSTRIES(i)
i->index = j++;
_total_industries = 0; _total_industries = 0;
_industry_sort_dirty = true; _industry_sort_dirty = true;
} }
@ -1894,14 +1901,13 @@ static const byte _industry_desc[] = {
static void Save_INDY() static void Save_INDY()
{ {
Industry *ind; Industry *ind;
int i = 0;
// Write the vehicles // Write the vehicles
FOR_ALL_INDUSTRIES(ind) { FOR_ALL_INDUSTRIES(ind) {
if (ind->xy != 0) { if (ind->xy != 0) {
SlSetArrayIndex(i); SlSetArrayIndex(ind->index);
SlObject(ind, _industry_desc); SlObject(ind, _industry_desc);
} }
i++;
} }
} }
@ -1910,7 +1916,9 @@ static void Load_INDY()
int index; int index;
_total_industries = 0; _total_industries = 0;
while ((index = SlIterateArray()) != -1) { while ((index = SlIterateArray()) != -1) {
SlObject(DEREF_INDUSTRY(index), _industry_desc); Industry *i = GetIndustry(index);
SlObject(i, _industry_desc);
if (index > _total_industries) _total_industries = index; if (index > _total_industries) _total_industries = index;
} }
} }

View File

@ -275,7 +275,7 @@ static void IndustryViewWndProc(Window *w, WindowEvent *e)
// in editor, use bulldoze to destroy industry // in editor, use bulldoze to destroy industry
// Destroy Industry button costing money removed per request of dominik // Destroy Industry button costing money removed per request of dominik
//w->disabled_state = (_patches.extra_dynamite && !_networking && _game_mode != GM_EDITOR) ? 0 : (1 << 6); //w->disabled_state = (_patches.extra_dynamite && !_networking && _game_mode != GM_EDITOR) ? 0 : (1 << 6);
i = DEREF_INDUSTRY(w->window_number); i = GetIndustry(w->window_number);
SetDParam(0, i->town->index); SetDParam(0, i->town->index);
SetDParam(1, i->type + STR_4802_COAL_MINE); SetDParam(1, i->type + STR_4802_COAL_MINE);
DrawWindowWidgets(w); DrawWindowWidgets(w);
@ -316,12 +316,12 @@ static void IndustryViewWndProc(Window *w, WindowEvent *e)
case WE_CLICK: case WE_CLICK:
switch(e->click.widget) { switch(e->click.widget) {
case 6: case 6:
i = DEREF_INDUSTRY(w->window_number); i = GetIndustry(w->window_number);
ScrollMainWindowToTile(i->xy + TILE_XY(1,1)); ScrollMainWindowToTile(i->xy + TILE_XY(1,1));
break; break;
case 7: case 7:
// Destroy Industry button costing money removed per request of dominik // Destroy Industry button costing money removed per request of dominik
//i = DEREF_INDUSTRY(w->window_number); //i = GetIndustry(w->window_number);
/* passing only i->xy is not safe if industry has a weird shape like: /* passing only i->xy is not safe if industry has a weird shape like:
_ X X _ X X
X X X X X X
@ -365,7 +365,7 @@ void ShowIndustryViewWindow(int industry)
w = AllocateWindowDescFront(&_industry_view_desc, industry); w = AllocateWindowDescFront(&_industry_view_desc, industry);
if (w) { if (w) {
w->flags4 |= WF_DISABLE_VP_SCROLL; w->flags4 |= WF_DISABLE_VP_SCROLL;
i = DEREF_INDUSTRY(w->window_number); i = GetIndustry(w->window_number);
AssignWindowViewport(w, 3, 17, 0xFE, 0x56, i->xy + TILE_XY(1,1), 1); AssignWindowViewport(w, 3, 17, 0xFE, 0x56, i->xy + TILE_XY(1,1), 1);
} }
} }
@ -385,7 +385,6 @@ static const Widget _industry_directory_widgets[] = {
{ WIDGETS_END}, { WIDGETS_END},
}; };
static uint16 _industry_sort[lengthof(_industries)];
static uint _num_industry_sort; static uint _num_industry_sort;
static char _bufcache[96]; static char _bufcache[96];
@ -397,8 +396,8 @@ static int CDECL GeneralIndustrySorter(const void *a, const void *b)
{ {
char buf1[96]; char buf1[96];
byte val; byte val;
Industry *i = DEREF_INDUSTRY(*(const uint16*)a); Industry *i = GetIndustry(*(const uint16*)a);
Industry *j = DEREF_INDUSTRY(*(const uint16*)b); Industry *j = GetIndustry(*(const uint16*)b);
int r = 0; int r = 0;
switch (_industry_sort_order >> 1) { switch (_industry_sort_order >> 1) {
@ -457,13 +456,16 @@ static int CDECL GeneralIndustrySorter(const void *a, const void *b)
static void MakeSortedIndustryList() static void MakeSortedIndustryList()
{ {
Industry *i; Industry *i;
int n = 0, index = 0; int n = 0;
/* Create array for sorting */
_industry_sort = realloc(_industry_sort, _industries_size * sizeof(_industry_sort[0]));
if (_industry_sort == NULL)
error("Could not allocate memory for the industry-sorting-list");
FOR_ALL_INDUSTRIES(i) { FOR_ALL_INDUSTRIES(i) {
if(i->xy) if(i->xy)
_industry_sort[n++] = index; _industry_sort[n++] = i->index;
index++;
} }
_num_industry_sort = n; _num_industry_sort = n;
_last_industry_idx = 0xFFFF; // used for "cache" _last_industry_idx = 0xFFFF; // used for "cache"
@ -497,7 +499,7 @@ static void IndustryDirectoryWndProc(Window *w, WindowEvent *e)
n = 0; n = 0;
while (p < _num_industry_sort) { while (p < _num_industry_sort) {
i = DEREF_INDUSTRY(_industry_sort[p]); i = GetIndustry(_industry_sort[p]);
SetDParam(0, i->town->index); SetDParam(0, i->town->index);
SetDParam(1, i->type + STR_4802_COAL_MINE); SetDParam(1, i->type + STR_4802_COAL_MINE);
if (i->produced_cargo[0] != 0xFF) { if (i->produced_cargo[0] != 0xFF) {
@ -558,7 +560,7 @@ static void IndustryDirectoryWndProc(Window *w, WindowEvent *e)
return; return;
p = y + w->vscroll.pos; p = y + w->vscroll.pos;
if (p < _num_industry_sort) { if (p < _num_industry_sort) {
c = DEREF_INDUSTRY(_industry_sort[p]); c = GetIndustry(_industry_sort[p]);
ScrollMainWindowToTile(c->xy); ScrollMainWindowToTile(c->xy);
} }
} break; } break;

12
misc.c
View File

@ -607,6 +607,7 @@ static const uint16 _autosave_months[] = {
void IncreaseDate() void IncreaseDate()
{ {
const int vehicles_per_day = (1 << (sizeof(_date_fract) * 8)) / 885;
int i,ctr,t; int i,ctr,t;
YearMonthDay ymd; YearMonthDay ymd;
@ -621,15 +622,15 @@ void IncreaseDate()
65536 / 885 = 74; 74x12 = 888. So max 888. Any vehicles above that were not _on_new_vehicle_day_proc'd 65536 / 885 = 74; 74x12 = 888. So max 888. Any vehicles above that were not _on_new_vehicle_day_proc'd
eg. aged. eg. aged.
So new code updates it for max vehicles. So new code updates it for max vehicles.
(NUM_VEHICLES / maximum number of times ctr is incremented before reset ) + 1 (to get last vehicles too) (_vehicles_size / maximum number of times ctr is incremented before reset ) + 1 (to get last vehicles too)
max size of _date_fract / 885 (added each tick) is number of times before ctr is reset. max size of _date_fract / 885 (added each tick) is number of times before ctr is reset.
Calculation might look complicated, but compiler just replaces it with 35, so that's ok Calculation might look complicated, but compiler just replaces it with 35, so that's ok
*/ */
ctr = _vehicle_id_ctr_day; ctr = _vehicle_id_ctr_day;
for(i=0; i!=(NUM_VEHICLES / ((1<<sizeof(_date_fract)*8) / 885)) + 1 && ctr != lengthof(_vehicles); i++) { for (i = 0; i != (_vehicles_size / vehicles_per_day) + 1 && ctr != _vehicles_size; i++) {
Vehicle *v = &_vehicles[ctr++]; Vehicle *v = GetVehicle(ctr++);
if ((t=v->type) != 0) if ((t = v->type) != 0)
_on_new_vehicle_day_proc[t - 0x10](v); _on_new_vehicle_day_proc[t - 0x10](v);
} }
_vehicle_id_ctr_day = ctr; _vehicle_id_ctr_day = ctr;
@ -637,7 +638,8 @@ void IncreaseDate()
/* increase day, and check if a new day is there? */ /* increase day, and check if a new day is there? */
_tick_counter++; _tick_counter++;
if ( (_date_fract += 885) >= 885) _date_fract += 885;
if (_date_fract >= 885)
return; return;
/* yeah, increse day counter and call various daily loops */ /* yeah, increse day counter and call various daily loops */

View File

@ -165,7 +165,7 @@ static void NewsWindowProc(Window *w, WindowEvent *e)
case 0: { case 0: {
NewsItem *ni = WP(w, news_d).ni; NewsItem *ni = WP(w, news_d).ni;
if (ni->flags & NF_VEHICLE) { if (ni->flags & NF_VEHICLE) {
Vehicle *v = &_vehicles[ni->data_a]; Vehicle *v = GetVehicle(ni->data_a);
ScrollMainWindowTo(v->x_pos, v->y_pos); ScrollMainWindowTo(v->x_pos, v->y_pos);
} else if (ni->flags & NF_TILE) { } else if (ni->flags & NF_TILE) {
if (!ScrollMainWindowToTile(ni->data_a) && ni->data_b != 0) if (!ScrollMainWindowToTile(ni->data_a) && ni->data_b != 0)

View File

@ -504,7 +504,7 @@ assert_compile(sizeof(OldMain) == 487801 + 256*256*2);
#endif #endif
#define REMAP_TOWN_IDX(x) (x - (0x0459154 - 0x0458EF0)) / sizeof(OldTown) #define REMAP_TOWN_IDX(x) (x - (0x0459154 - 0x0458EF0)) / sizeof(OldTown)
#define REMAP_TOWN_PTR(x) DEREF_TOWN( REMAP_TOWN_IDX(x) ) #define REMAP_TOWN_PTR(x) GetTown( REMAP_TOWN_IDX(x) )
#define REMAP_ORDER_IDX(x) (x - (0x045AB08 - 0x0458EF0)) / sizeof(uint16) #define REMAP_ORDER_IDX(x) (x - (0x045AB08 - 0x0458EF0)) / sizeof(uint16)
@ -584,9 +584,14 @@ static void LoadSavegameBytes(void *p, size_t count)
extern uint32 GetOldTownName(uint32 townnameparts, byte old_town_name_type); extern uint32 GetOldTownName(uint32 townnameparts, byte old_town_name_type);
static void FixTown(Town *t, OldTown *o, int num, byte town_name_type) static void FixTown(OldTown *o, int num, byte town_name_type)
{ {
Town *t;
uint i;
do { do {
t = GetTown(i);
t->xy = o->xy; t->xy = o->xy;
t->population = o->population; t->population = o->population;
t->townnametype = o->townnametype; t->townnametype = o->townnametype;
@ -622,12 +627,17 @@ static void FixTown(Town *t, OldTown *o, int num, byte town_name_type)
t->act_water = o->act_water; t->act_water = o->act_water;
t->road_build_months = o->road_build_months; t->road_build_months = o->road_build_months;
t->fund_buildings_months = o->fund_buildings_months; t->fund_buildings_months = o->fund_buildings_months;
} while (t++,o++,--num); } while (i++,o++,--num);
} }
static void FixIndustry(Industry *i, OldIndustry *o, int num) static void FixIndustry(OldIndustry *o, int num)
{ {
Industry *i;
uint j = 0;
do { do {
i = GetIndustry(j);
i->xy = o->xy; i->xy = o->xy;
i->town = REMAP_TOWN_PTR(o->town); i->town = REMAP_TOWN_PTR(o->town);
i->width = o->width; i->width = o->width;
@ -664,7 +674,7 @@ static void FixIndustry(Industry *i, OldIndustry *o, int num)
i->last_prod_year = o->last_prod_year; i->last_prod_year = o->last_prod_year;
i->counter = o->counter; i->counter = o->counter;
i->was_cargo_delivered = o->was_cargo_delivered; i->was_cargo_delivered = o->was_cargo_delivered;
} while (i++,o++,--num); } while (j++,o++,--num);
} }
static void FixGoodsEntry(GoodsEntry *g, OldGoodsEntry *o, int num) static void FixGoodsEntry(GoodsEntry *g, OldGoodsEntry *o, int num)
@ -680,9 +690,14 @@ static void FixGoodsEntry(GoodsEntry *g, OldGoodsEntry *o, int num)
} while (g++,o++,--num); } while (g++,o++,--num);
} }
static void FixStation(Station *s, OldStation *o, int num) static void FixStation(OldStation *o, int num)
{ {
Station *s;
uint i = 0;
do { do {
s = GetStation(i);
s->xy = o->xy; s->xy = o->xy;
s->town = REMAP_TOWN_PTR(o->town); s->town = REMAP_TOWN_PTR(o->town);
s->bus_tile = o->bus_tile; s->bus_tile = o->bus_tile;
@ -713,7 +728,7 @@ static void FixStation(Station *s, OldStation *o, int num)
s->blocked_months_obsolete = o->blocked_months_obsolete; s->blocked_months_obsolete = o->blocked_months_obsolete;
s->airport_flags = o->airport_flags; s->airport_flags = o->airport_flags;
s->last_vehicle = o->last_vehicle; s->last_vehicle = o->last_vehicle;
} while (s++,o++,--num); } while (i++,o++,--num);
} }
static void FixDepot(Depot *n, OldDepot *o, int num) static void FixDepot(Depot *n, OldDepot *o, int num)
@ -724,9 +739,14 @@ static void FixDepot(Depot *n, OldDepot *o, int num)
} while (n++,o++,--num); } while (n++,o++,--num);
} }
static void FixVehicle(Vehicle *n, OldVehicle *o, int num) static void FixVehicle(OldVehicle *o, int num)
{ {
Vehicle *n;
uint i = 0;
do { do {
n = GetVehicle(i);
n->type = o->type; n->type = o->type;
n->subtype = o->subtype; n->subtype = o->subtype;
@ -793,7 +813,7 @@ static void FixVehicle(Vehicle *n, OldVehicle *o, int num)
n->reliability_spd_dec = o->reliability_spd_dec; n->reliability_spd_dec = o->reliability_spd_dec;
n->profit_this_year = o->profit_this_year; n->profit_this_year = o->profit_this_year;
n->profit_last_year = o->profit_last_year; n->profit_last_year = o->profit_last_year;
n->next = o->next_in_chain == 0xffff ? NULL : &_vehicles[o->next_in_chain]; n->next = (o->next_in_chain == 0xFFFF) ? NULL : GetVehicle(o->next_in_chain);
n->value = o->value; n->value = o->value;
n->string_id = RemapOldStringID(o->string_id); n->string_id = RemapOldStringID(o->string_id);
@ -833,7 +853,7 @@ static void FixVehicle(Vehicle *n, OldVehicle *o, int num)
n->u.disaster.unk2 = o->u.disaster.unk2; n->u.disaster.unk2 = o->u.disaster.unk2;
break; break;
} }
} while (n++,o++,--num); } while (i++,o++,--num);
} }
static void FixSubsidy(Subsidy *n, OldSubsidy *o, int num) static void FixSubsidy(Subsidy *n, OldSubsidy *o, int num)
@ -1407,12 +1427,12 @@ bool LoadOldSaveGame(const char *file)
_order_array[i] = UnpackOldOrder(m->order_list[i]); _order_array[i] = UnpackOldOrder(m->order_list[i]);
_ptr_to_next_order = _order_array + REMAP_ORDER_IDX(m->ptr_to_next_order); _ptr_to_next_order = _order_array + REMAP_ORDER_IDX(m->ptr_to_next_order);
FixTown(_towns, m->town_list, lengthof(m->town_list), m->town_name_type); FixTown(m->town_list, lengthof(m->town_list), m->town_name_type);
FixIndustry(_industries, m->industries, lengthof(m->industries)); FixIndustry(m->industries, lengthof(m->industries));
FixStation(_stations, m->stations, lengthof(m->stations)); FixStation(m->stations, lengthof(m->stations));
FixDepot(_depots, m->depots, lengthof(m->depots)); FixDepot(_depots, m->depots, lengthof(m->depots));
FixVehicle(_vehicles, m->vehicles, lengthof(m->vehicles)); FixVehicle(m->vehicles, lengthof(m->vehicles));
FixSubsidy(_subsidies, m->subsidies, lengthof(m->subsidies)); FixSubsidy(_subsidies, m->subsidies, lengthof(m->subsidies));
FixPlayer(_players, m->players, lengthof(m->players), m->town_name_type); FixPlayer(_players, m->players, lengthof(m->players), m->town_name_type);

View File

@ -13,7 +13,7 @@
*/ */
int32 CmdInsertOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 CmdInsertOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *v = &_vehicles[p1 & 0xFFFF]; Vehicle *v = GetVehicle(p1 & 0xFFFF);
int sel = p1 >> 16; int sel = p1 >> 16;
Order new_order = UnpackOrder(p2); Order new_order = UnpackOrder(p2);
@ -26,8 +26,8 @@ int32 CmdInsertOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
sel != 0 && v->schedule_ptr[sel - 1].type == OT_GOTO_STATION) { sel != 0 && v->schedule_ptr[sel - 1].type == OT_GOTO_STATION) {
int dist = GetTileDist( int dist = GetTileDist(
DEREF_STATION(v->schedule_ptr[sel - 1].station)->xy, GetStation(v->schedule_ptr[sel - 1].station)->xy,
DEREF_STATION(new_order.station)->xy GetStation(new_order.station)->xy
); );
if (dist >= 130) if (dist >= 130)
return_cmd_error(STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO); return_cmd_error(STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO);
@ -94,7 +94,7 @@ static int32 DecloneOrder(Vehicle *dst, uint32 flags)
*/ */
int32 CmdDeleteOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 CmdDeleteOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *v = &_vehicles[p1], *u; Vehicle *v = GetVehicle(p1), *u;
uint sel = (uint)p2; uint sel = (uint)p2;
_error_message = STR_EMPTY; _error_message = STR_EMPTY;
@ -141,7 +141,7 @@ int32 CmdDeleteOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
int32 CmdSkipOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 CmdSkipOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
Vehicle *v = &_vehicles[p1]; Vehicle *v = GetVehicle(p1);
{ {
byte b = v->cur_order_index + 1; byte b = v->cur_order_index + 1;
@ -168,7 +168,7 @@ int32 CmdSkipOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
*/ */
int32 CmdModifyOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 CmdModifyOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *v = &_vehicles[p1]; Vehicle *v = GetVehicle(p1);
byte sel = (byte)p2; byte sel = (byte)p2;
Order *sched; Order *sched;
@ -219,7 +219,7 @@ int32 CmdModifyOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *dst = &_vehicles[p1 & 0xFFFF]; Vehicle *dst = GetVehicle(p1 & 0xFFFF);
if (!(dst->type && dst->owner == _current_player)) if (!(dst->type && dst->owner == _current_player))
return CMD_ERROR; return CMD_ERROR;
@ -228,7 +228,7 @@ int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
// share vehicle orders? // share vehicle orders?
case 0: { case 0: {
Vehicle *src = &_vehicles[p1 >> 16]; Vehicle *src = GetVehicle(p1 >> 16);
// sanity checks // sanity checks
if (!(src->owner == _current_player && dst->type == src->type && dst != src)) if (!(src->owner == _current_player && dst->type == src->type && dst != src))
@ -255,7 +255,7 @@ int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
// copy vehicle orders? // copy vehicle orders?
case 1: { case 1: {
Vehicle *src = &_vehicles[p1 >> 16]; Vehicle *src = GetVehicle(p1 >> 16);
int delta; int delta;
// sanity checks // sanity checks
@ -269,7 +269,7 @@ int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
for (i = src->schedule_ptr; i->type != OT_NOTHING; ++i) { for (i = src->schedule_ptr; i->type != OT_NOTHING; ++i) {
if (i->type == OT_GOTO_STATION) { if (i->type == OT_GOTO_STATION) {
const Station *st = DEREF_STATION(i->station); const Station *st = GetStation(i->station);
required_dst = (dst->cargo_type == CT_PASSENGERS) ? st->bus_tile : st->lorry_tile; required_dst = (dst->cargo_type == CT_PASSENGERS) ? st->bus_tile : st->lorry_tile;
if ( !required_dst ) if ( !required_dst )
return CMD_ERROR; return CMD_ERROR;
@ -366,7 +366,7 @@ int32 CmdRestoreOrderIndex(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
// nonsense to update the windows, since, train rebought will have its window deleted // nonsense to update the windows, since, train rebought will have its window deleted
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
Vehicle *v = &_vehicles[p1]; Vehicle *v = GetVehicle(p1);
v->service_interval = (uint16)(p2>>16); v->service_interval = (uint16)(p2>>16);
v->cur_order_index = (byte)(p2&0xFFFF); v->cur_order_index = (byte)(p2&0xFFFF);
} }
@ -415,7 +415,7 @@ int CheckOrders(Vehicle *v)
//I uncommented this in order not to get two error messages //I uncommented this in order not to get two error messages
//when two identical entries are in the list //when two identical entries are in the list
n_st++; n_st++;
st = DEREF_STATION(order.station); st = GetStation(order.station);
required_tile = GetStationTileForVehicle(v,st); required_tile = GetStationTileForVehicle(v,st);
if (!required_tile) problem_type = 3; if (!required_tile) problem_type = 3;
} }

View File

@ -13,7 +13,7 @@
static int OrderGetSel(Window *w) static int OrderGetSel(Window *w)
{ {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
const Order *sched = v->schedule_ptr; const Order *sched = v->schedule_ptr;
int num = WP(w,order_d).sel; int num = WP(w,order_d).sel;
int count = 0; int count = 0;
@ -41,7 +41,7 @@ static void DrawOrdersWindow(Window *w)
StringID str; StringID str;
bool shared_schedule; bool shared_schedule;
v = &_vehicles[w->window_number]; v = GetVehicle(w->window_number);
w->disabled_state = (v->owner == _local_player) ? 0 : 0x3F0; w->disabled_state = (v->owner == _local_player) ? 0 : 0x3F0;
@ -237,7 +237,7 @@ static Order GetOrderCmdFromTile(Vehicle *v, uint tile)
} }
if (IS_TILETYPE(tile, MP_STATION)) { if (IS_TILETYPE(tile, MP_STATION)) {
st = DEREF_STATION(st_index = _map2[tile]); st = GetStation(st_index = _map2[tile]);
if (st->owner == _current_player || st->owner == OWNER_NONE) { if (st->owner == _current_player || st->owner == OWNER_NONE) {
byte facil; byte facil;
@ -314,7 +314,7 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
break; break;
case WE_CLICK: { case WE_CLICK: {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
int mode; int mode;
switch(e->click.widget) { switch(e->click.widget) {
case 2: {/* orders list */ case 2: {/* orders list */
@ -331,7 +331,7 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
int xy = 0; int xy = 0;
switch (ord.type) { switch (ord.type) {
case OT_GOTO_STATION: /* station order */ case OT_GOTO_STATION: /* station order */
xy = _stations[ord.station].xy ; xy = GetStation(ord.station)->xy ;
break; break;
case OT_GOTO_DEPOT: /* goto depot order */ case OT_GOTO_DEPOT: /* goto depot order */
xy = _depots[ord.station].xy; xy = _depots[ord.station].xy;
@ -389,7 +389,7 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
case WE_RCLICK: { case WE_RCLICK: {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
if (e->click.widget != 8) break; if (e->click.widget != 8) break;
if (v->schedule_ptr[OrderGetSel(w)].type == OT_GOTO_DEPOT) if (v->schedule_ptr[OrderGetSel(w)].type == OT_GOTO_DEPOT)
GuiShowTooltips(STR_SERVICE_HINT); GuiShowTooltips(STR_SERVICE_HINT);
@ -403,7 +403,7 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
} break; } break;
case WE_PLACE_OBJ: { case WE_PLACE_OBJ: {
OrdersPlaceObj(&_vehicles[w->window_number], e->place.tile, w); OrdersPlaceObj(GetVehicle(w->window_number), e->place.tile, w);
} break; } break;
case WE_ABORT_PLACE_OBJ: { case WE_ABORT_PLACE_OBJ: {
@ -424,7 +424,7 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
*/ */
if (v && HASBIT(w->click_state, 7)) { if (v && HASBIT(w->click_state, 7)) {
_place_clicked_vehicle = NULL; _place_clicked_vehicle = NULL;
HandleOrderVehClick(&_vehicles[w->window_number], v, w); HandleOrderVehClick(GetVehicle(w->window_number), v, w);
} }
} break; } break;

View File

@ -1453,7 +1453,7 @@ static Station *ComposeWaypointStation(uint tile)
stat.train_tile = stat.xy = waypt->xy; stat.train_tile = stat.xy = waypt->xy;
/* FIXME - We should always keep town. */ /* FIXME - We should always keep town. */
stat.town = waypt->town_or_string & 0xC000 ? &_towns[waypt->town_or_string & 0xFF] : NULL; stat.town = waypt->town_or_string & 0xC000 ? GetTown(waypt->town_or_string & 0xFF) : NULL;
stat.string_id = waypt->town_or_string & 0xC000 ? /* FIXME? */ 0 : waypt->town_or_string; stat.string_id = waypt->town_or_string & 0xC000 ? /* FIXME? */ 0 : waypt->town_or_string;
stat.build_date = waypt->build_date; stat.build_date = waypt->build_date;
stat.class_id = 6; stat.stat_id = waypt->stat_id; stat.class_id = 6; stat.stat_id = waypt->stat_id;

View File

@ -199,7 +199,7 @@ int32 CmdStartStopRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *v; Vehicle *v;
v = &_vehicles[p1]; v = GetVehicle(p1);
if (v->type != VEH_Road || !CheckOwnership(v->owner)) if (v->type != VEH_Road || !CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -213,7 +213,7 @@ int32 CmdStartStopRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return 0; return 0;
} }
// p1 = vehicle index in &_vehicles[] // p1 = vehicle index in GetVehicle()
// p2 not used // p2 not used
int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
@ -221,7 +221,7 @@ int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
v = &_vehicles[p1]; v = GetVehicle(p1);
if (v->type != VEH_Road || !CheckOwnership(v->owner)) if (v->type != VEH_Road || !CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -291,7 +291,7 @@ static int FindClosestRoadDepot(Vehicle *v)
int32 CmdSendRoadVehToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 CmdSendRoadVehToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *v = &_vehicles[p1]; Vehicle *v = GetVehicle(p1);
int depot; int depot;
if (v->type != VEH_Road || !CheckOwnership(v->owner)) if (v->type != VEH_Road || !CheckOwnership(v->owner))
@ -327,7 +327,7 @@ int32 CmdTurnRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *v; Vehicle *v;
v = &_vehicles[p1]; v = GetVehicle(p1);
if (v->type != VEH_Road || !CheckOwnership(v->owner)) if (v->type != VEH_Road || !CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -352,7 +352,7 @@ int32 CmdChangeRoadVehServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p
{ {
Vehicle *v; Vehicle *v;
v = &_vehicles[p1]; v = GetVehicle(p1);
if (v->type != VEH_Road || !CheckOwnership(v->owner)) if (v->type != VEH_Road || !CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -396,7 +396,7 @@ static void UpdateRoadVehDeltaXY(Vehicle *v)
static void ClearCrashedStation(Vehicle *v) static void ClearCrashedStation(Vehicle *v)
{ {
uint tile = v->tile; uint tile = v->tile;
Station *st = DEREF_STATION(_map2[tile]); Station *st = GetStation(_map2[tile]);
byte *b, bb; byte *b, bb;
b = (_map5[tile] >= 0x47) ? &st->bus_stop_status : &st->truck_stop_status; b = (_map5[tile] >= 0x47) ? &st->bus_stop_status : &st->truck_stop_status;
@ -594,7 +594,7 @@ static void ProcessRoadVehOrder(Vehicle *v)
if (order.type == OT_GOTO_STATION) { if (order.type == OT_GOTO_STATION) {
if (order.station == v->last_station_visited) if (order.station == v->last_station_visited)
v->last_station_visited = 0xFFFF; v->last_station_visited = 0xFFFF;
st = DEREF_STATION(order.station); st = GetStation(order.station);
v->dest_tile = v->cargo_type==CT_PASSENGERS ? st->bus_tile : st->lorry_tile; v->dest_tile = v->cargo_type==CT_PASSENGERS ? st->bus_tile : st->lorry_tile;
} else if (order.type == OT_GOTO_DEPOT) { } else if (order.type == OT_GOTO_DEPOT) {
v->dest_tile = _depots[order.station].xy; v->dest_tile = _depots[order.station].xy;
@ -951,7 +951,7 @@ static int RoadFindPathToDest(Vehicle *v, uint tile, int direction)
} else if (IS_TILETYPE(tile, MP_STATION)) { } else if (IS_TILETYPE(tile, MP_STATION)) {
if (_map_owner[tile] == OWNER_NONE || _map_owner[tile] == v->owner) { if (_map_owner[tile] == OWNER_NONE || _map_owner[tile] == v->owner) {
/* Our station */ /* Our station */
Station *st = DEREF_STATION(_map2[tile]); Station *st = GetStation(_map2[tile]);
byte val = _map5[tile]; byte val = _map5[tile];
if (v->cargo_type != CT_PASSENGERS) { if (v->cargo_type != CT_PASSENGERS) {
if (IS_BYTE_INSIDE(val, 0x43, 0x47) && (_patches.roadveh_queue || st->truck_stop_status&3)) if (IS_BYTE_INSIDE(val, 0x43, 0x47) && (_patches.roadveh_queue || st->truck_stop_status&3))
@ -1211,7 +1211,7 @@ again:
if (IS_BYTE_INSIDE(v->u.road.state, 0x20, 0x30) && IS_TILETYPE(v->tile, MP_STATION)) { if (IS_BYTE_INSIDE(v->u.road.state, 0x20, 0x30) && IS_TILETYPE(v->tile, MP_STATION)) {
if ((tmp&7) >= 6) { v->cur_speed = 0; return; } if ((tmp&7) >= 6) { v->cur_speed = 0; return; }
if (IS_BYTE_INSIDE(_map5[v->tile], 0x43, 0x4B)) { if (IS_BYTE_INSIDE(_map5[v->tile], 0x43, 0x4B)) {
Station *st = DEREF_STATION(_map2[v->tile]); Station *st = GetStation(_map2[v->tile]);
byte *b; byte *b;
if (_map5[v->tile] >= 0x47) { if (_map5[v->tile] >= 0x47) {
@ -1307,7 +1307,7 @@ again:
_road_veh_data_1[v->u.road.state - 0x20 + (_opt.road_side<<4)] == v->u.road.frame) { _road_veh_data_1[v->u.road.state - 0x20 + (_opt.road_side<<4)] == v->u.road.frame) {
byte *b; byte *b;
st = DEREF_STATION(_map2[v->tile]); st = GetStation(_map2[v->tile]);
b = IS_BYTE_INSIDE(_map5[v->tile], 0x43, 0x47) ? &st->truck_stop_status : &st->bus_stop_status; b = IS_BYTE_INSIDE(_map5[v->tile], 0x43, 0x47) ? &st->truck_stop_status : &st->bus_stop_status;
if (v->current_order.type != OT_LEAVESTATION && if (v->current_order.type != OT_LEAVESTATION &&
@ -1487,7 +1487,7 @@ void OnNewDay_RoadVeh(Vehicle *v)
/* update destination */ /* update destination */
if (v->current_order.type == OT_GOTO_STATION) { if (v->current_order.type == OT_GOTO_STATION) {
st = DEREF_STATION(v->current_order.station); st = GetStation(v->current_order.station);
if ((tile=(v->cargo_type==CT_PASSENGERS ? st->bus_tile : st->lorry_tile)) != 0) if ((tile=(v->cargo_type==CT_PASSENGERS ? st->bus_tile : st->lorry_tile)) != 0)
v->dest_tile = tile; v->dest_tile = tile;
} }

View File

@ -45,7 +45,7 @@ static void DrawRoadVehImage(Vehicle *v, int x, int y, VehicleID selection)
static void RoadVehDetailsWndProc(Window *w, WindowEvent *e) static void RoadVehDetailsWndProc(Window *w, WindowEvent *e)
{ {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
StringID str; StringID str;
int mod; int mod;
@ -204,7 +204,7 @@ static void RoadVehViewWndProc(Window *w, WindowEvent *e)
{ {
switch(e->event) { switch(e->event) {
case WE_PAINT: { case WE_PAINT: {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
StringID str; StringID str;
w->disabled_state = (v->owner != _local_player) ? (1<<8 | 1<<7) : 0; w->disabled_state = (v->owner != _local_player) ? (1<<8 | 1<<7) : 0;
@ -258,7 +258,7 @@ static void RoadVehViewWndProc(Window *w, WindowEvent *e)
} break; } break;
case WE_CLICK: { case WE_CLICK: {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
switch(e->click.widget) { switch(e->click.widget) {
case 5: /* start stop */ case 5: /* start stop */
@ -380,7 +380,7 @@ void CcBuildRoadVeh(bool success, uint tile, uint32 p1, uint32 p2)
if (!success) return; if (!success) return;
v = &_vehicles[_new_roadveh_id]; v = GetVehicle(_new_roadveh_id);
if (v->tile == _backup_orders_tile) { if (v->tile == _backup_orders_tile) {
_backup_orders_tile = 0; _backup_orders_tile = 0;
RestoreVehicleOrders(v, _backup_orders_data); RestoreVehicleOrders(v, _backup_orders_data);
@ -665,7 +665,7 @@ static void RoadDepotWndProc(Window *w, WindowEvent *e)
HandleButtonClick(w, 5); HandleButtonClick(w, 5);
v = &_vehicles[WP(w,traindepot_d).sel]; v = GetVehicle(WP(w,traindepot_d).sel);
WP(w,traindepot_d).sel = INVALID_VEHICLE; WP(w,traindepot_d).sel = INVALID_VEHICLE;
_backup_orders_tile = v->tile; _backup_orders_tile = v->tile;
@ -800,7 +800,7 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e)
w->widget[1].unkA = STR_9001_ROAD_VEHICLES; w->widget[1].unkA = STR_9001_ROAD_VEHICLES;
} else { } else {
/* Station Name -- (###) Road vehicles */ /* Station Name -- (###) Road vehicles */
SetDParam(0, DEREF_STATION(station)->index); SetDParam(0, GetStation(station)->index);
SetDParam(1, w->vscroll.count); SetDParam(1, w->vscroll.count);
w->widget[1].unkA = STR_SCHEDULED_ROAD_VEHICLES; w->widget[1].unkA = STR_SCHEDULED_ROAD_VEHICLES;
} }
@ -814,7 +814,7 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e)
max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length); max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length);
for (i = w->vscroll.pos; i < max; ++i) { for (i = w->vscroll.pos; i < max; ++i) {
Vehicle *v = DEREF_VEHICLE(vl->sort_list[i].index); Vehicle *v = GetVehicle(vl->sort_list[i].index);
StringID str; StringID str;
assert(v->type == VEH_Road && v->owner == owner); assert(v->type == VEH_Road && v->owner == owner);
@ -865,7 +865,7 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e)
if (id_v >= vl->list_length) return; // click out of list bound if (id_v >= vl->list_length) return; // click out of list bound
v = DEREF_VEHICLE(vl->sort_list[id_v].index); v = GetVehicle(vl->sort_list[id_v].index);
assert(v->type == VEH_Road && v->owner == owner); assert(v->type == VEH_Road && v->owner == owner);

View File

@ -243,7 +243,7 @@ static void ProcessShipOrder(Vehicle *v)
if (order.station == v->last_station_visited) if (order.station == v->last_station_visited)
v->last_station_visited = 0xFFFF; v->last_station_visited = 0xFFFF;
st = DEREF_STATION(order.station); st = GetStation(order.station);
if (st->dock_tile != 0) { if (st->dock_tile != 0) {
v->dest_tile = TILE_ADD(st->dock_tile, ToTileIndexDiff(_dock_offs[_map5[st->dock_tile]-0x4B])); v->dest_tile = TILE_ADD(st->dock_tile, ToTileIndexDiff(_dock_offs[_map5[st->dock_tile]-0x4B]));
} }
@ -679,7 +679,7 @@ static void ShipController(Vehicle *v)
v->last_station_visited = v->current_order.station; v->last_station_visited = v->current_order.station;
/* Process station in the schedule. Don't do that for buoys (HVOT_BUOY) */ /* Process station in the schedule. Don't do that for buoys (HVOT_BUOY) */
st = DEREF_STATION(v->current_order.station); st = GetStation(v->current_order.station);
if (!(st->had_vehicle_of_type & HVOT_BUOY) if (!(st->had_vehicle_of_type & HVOT_BUOY)
&& (st->facilities & FACIL_DOCK)) { /* ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations */ && (st->facilities & FACIL_DOCK)) { /* ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations */
v->current_order.type = OT_LOADING; v->current_order.type = OT_LOADING;
@ -884,7 +884,7 @@ int32 CmdSellShip(int x, int y, uint32 flags, uint32 p1, uint32 p2)
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner)) if (!CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -908,7 +908,7 @@ int32 CmdStartStopShip(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *v; Vehicle *v;
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner)) if (!CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -927,7 +927,7 @@ int32 CmdSendShipToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2)
Vehicle *v; Vehicle *v;
int depot; int depot;
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner)) if (!CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -960,7 +960,7 @@ int32 CmdChangeShipServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *v; Vehicle *v;
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner)) if (!CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -986,7 +986,7 @@ int32 CmdRefitShip(int x, int y, uint32 flags, uint32 p1, uint32 p2)
p2 = p2 & 0xFF; p2 = p2 & 0xFF;
SET_EXPENSES_TYPE(EXPENSES_SHIP_RUN); SET_EXPENSES_TYPE(EXPENSES_SHIP_RUN);
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner)) if (!CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;

View File

@ -46,7 +46,7 @@ static void ShipRefitWndProc(Window *w, WindowEvent *e)
{ {
switch(e->event) { switch(e->event) {
case WE_PAINT: { case WE_PAINT: {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
const byte *b; const byte *b;
int sel; int sel;
int x,y; int x,y;
@ -123,7 +123,7 @@ static void ShipRefitWndProc(Window *w, WindowEvent *e)
} break; } break;
case 4: /* refit button */ case 4: /* refit button */
if (WP(w,refit_d).cargo != 0xFF) { if (WP(w,refit_d).cargo != 0xFF) {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_SHIP | CMD_MSG(STR_9841_CAN_T_REFIT_SHIP))) if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_SHIP | CMD_MSG(STR_9841_CAN_T_REFIT_SHIP)))
DeleteWindow(w); DeleteWindow(w);
} }
@ -166,7 +166,7 @@ static void ShowShipRefitWindow(Vehicle *v)
static void ShipDetailsWndProc(Window *w, WindowEvent *e) static void ShipDetailsWndProc(Window *w, WindowEvent *e)
{ {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
StringID str; StringID str;
int mod; int mod;
@ -326,7 +326,7 @@ void CcBuildShip(bool success, uint tile, uint32 p1, uint32 p2)
Vehicle *v; Vehicle *v;
if (!success) return; if (!success) return;
v = &_vehicles[_new_ship_id]; v = GetVehicle(_new_ship_id);
if (v->tile == _backup_orders_tile) { if (v->tile == _backup_orders_tile) {
_backup_orders_tile = 0; _backup_orders_tile = 0;
RestoreVehicleOrders(v, _backup_orders_data); RestoreVehicleOrders(v, _backup_orders_data);
@ -484,7 +484,7 @@ static void ShowBuildShipWindow(TileIndex tile)
static void ShipViewWndProc(Window *w, WindowEvent *e) { static void ShipViewWndProc(Window *w, WindowEvent *e) {
switch(e->event) { switch(e->event) {
case WE_PAINT: { case WE_PAINT: {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
uint32 disabled = 1<<8; uint32 disabled = 1<<8;
StringID str; StringID str;
@ -546,7 +546,7 @@ static void ShipViewWndProc(Window *w, WindowEvent *e) {
} break; } break;
case WE_CLICK: { case WE_CLICK: {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
switch(e->click.widget) { switch(e->click.widget) {
case 5: /* start stop */ case 5: /* start stop */
@ -799,7 +799,7 @@ static void ShipDepotWndProc(Window *w, WindowEvent *e) {
HandleButtonClick(w, 5); HandleButtonClick(w, 5);
v = &_vehicles[WP(w,traindepot_d).sel]; v = GetVehicle(WP(w,traindepot_d).sel);
WP(w,traindepot_d).sel = INVALID_VEHICLE; WP(w,traindepot_d).sel = INVALID_VEHICLE;
_backup_orders_tile = v->tile; _backup_orders_tile = v->tile;
@ -882,7 +882,7 @@ static void DrawSmallShipSchedule(Vehicle *v, int x, int y) {
sel--; sel--;
if (sched->type == OT_GOTO_STATION) { if (sched->type == OT_GOTO_STATION) {
st = DEREF_STATION(sched->station); st = GetStation(sched->station);
if (!(st->had_vehicle_of_type & HVOT_BUOY)) { if (!(st->had_vehicle_of_type & HVOT_BUOY)) {
SetDParam(0, sched->station); SetDParam(0, sched->station);
@ -962,7 +962,7 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e)
w->widget[1].unkA = STR_9805_SHIPS; w->widget[1].unkA = STR_9805_SHIPS;
} else { } else {
/* Station Name -- (###) Trains */ /* Station Name -- (###) Trains */
SetDParam(0, DEREF_STATION(station)->index); SetDParam(0, GetStation(station)->index);
SetDParam(1, w->vscroll.count); SetDParam(1, w->vscroll.count);
w->widget[1].unkA = STR_SCHEDULED_SHIPS; w->widget[1].unkA = STR_SCHEDULED_SHIPS;
} }
@ -976,7 +976,7 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e)
max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length); max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length);
for (i = w->vscroll.pos; i < max; ++i) { for (i = w->vscroll.pos; i < max; ++i) {
Vehicle *v = DEREF_VEHICLE(vl->sort_list[i].index); Vehicle *v = GetVehicle(vl->sort_list[i].index);
StringID str; StringID str;
assert(v->type == VEH_Ship); assert(v->type == VEH_Ship);
@ -1028,7 +1028,7 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e)
if (id_v >= vl->list_length) return; // click out of list bound if (id_v >= vl->list_length) return; // click out of list bound
v = DEREF_VEHICLE(vl->sort_list[id_v].index); v = GetVehicle(vl->sort_list[id_v].index);
assert(v->type == VEH_Ship); assert(v->type == VEH_Ship);

View File

@ -94,13 +94,21 @@ void ShowStationViewWindow(int station);
void UpdateAllStationVirtCoord(); void UpdateAllStationVirtCoord();
VARDEF Station _stations[250]; VARDEF Station _stations[250];
VARDEF uint _stations_size;
VARDEF SortStruct *_station_sort;
static inline Station *GetStation(uint index)
{
assert(index < _stations_size);
return &_stations[index];
}
#define FOR_ALL_STATIONS(st) for(st = _stations; st != &_stations[_stations_size]; st++)
VARDEF bool _station_sort_dirty[MAX_PLAYERS]; VARDEF bool _station_sort_dirty[MAX_PLAYERS];
VARDEF bool _global_station_sort_dirty; VARDEF bool _global_station_sort_dirty;
#define DEREF_STATION(i) (&_stations[i])
#define FOR_ALL_STATIONS(st) for(st=_stations; st != endof(_stations); st++)
void GetProductionAroundTiles(uint *produced, uint tile, int w, int h, int rad); void GetProductionAroundTiles(uint *produced, uint tile, int w, int h, int rad);
void GetAcceptanceAroundTiles(uint *accepts, uint tile, int w, int h, int rad); void GetAcceptanceAroundTiles(uint *accepts, uint tile, int w, int h, int rad);
uint GetStationPlatforms(Station *st, uint tile); uint GetStationPlatforms(Station *st, uint tile);

View File

@ -25,6 +25,10 @@ const byte _airport_size_y[5] = {3, 6, 1, 6, 7 };
void ShowAircraftDepotWindow(uint tile); void ShowAircraftDepotWindow(uint tile);
extern void UpdateAirplanesOnNewStation(Station *st); extern void UpdateAirplanesOnNewStation(Station *st);
enum {
STATIONS_MIN_FREE_FOR_AI = 30
};
static void MarkStationDirty(Station *st) static void MarkStationDirty(Station *st)
{ {
if (st->sign.width_1 != 0) { if (st->sign.width_1 != 0) {
@ -73,7 +77,7 @@ static Station *GetStationAround(uint tile, int w, int h, int closest_station)
int t; int t;
t = _map2[tile_cur]; t = _map2[tile_cur];
{ {
Station *st = DEREF_STATION(t); Station *st = GetStation(t);
// you cannot take control of an oilrig!! // you cannot take control of an oilrig!!
if (st->airport_type == AT_OILRIG && st->facilities == (FACIL_AIRPORT|FACIL_DOCK)) if (st->airport_type == AT_OILRIG && st->facilities == (FACIL_AIRPORT|FACIL_DOCK))
continue; continue;
@ -87,7 +91,7 @@ static Station *GetStationAround(uint tile, int w, int h, int closest_station)
} }
} }
END_TILE_LOOP(tile_cur, w + 2, h + 2, tile - TILE_XY(1,1)) END_TILE_LOOP(tile_cur, w + 2, h + 2, tile - TILE_XY(1,1))
return (closest_station == -1) ? NULL : DEREF_STATION(closest_station); return (closest_station == -1) ? NULL : GetStation(closest_station);
} }
TileIndex GetStationTileForVehicle(Vehicle *v, Station *st) TileIndex GetStationTileForVehicle(Vehicle *v, Station *st)
@ -136,20 +140,19 @@ static bool CheckStationSpreadOut(Station *st, uint tile, int w, int h)
static Station *AllocateStation() static Station *AllocateStation()
{ {
Station *st, *a_free = NULL; Station *st, *a_free = NULL;
int count;
int num_free = 0; int num_free = 0;
int i; int i;
for(st = _stations, count = lengthof(_stations); count != 0; count--, st++) { FOR_ALL_STATIONS(st) {
if (st->xy == 0) { if (st->xy == 0) {
num_free++; num_free++;
if (a_free==NULL) if (a_free == NULL)
a_free = st; a_free = st;
} }
} }
if (a_free == NULL || if (a_free == NULL ||
(num_free < 30 && IS_HUMAN_PLAYER(_current_player))) { (num_free < STATIONS_MIN_FREE_FOR_AI && IS_HUMAN_PLAYER(_current_player))) {
_error_message = STR_3008_TOO_MANY_STATIONS_LOADING; _error_message = STR_3008_TOO_MANY_STATIONS_LOADING;
return NULL; return NULL;
} }
@ -961,7 +964,7 @@ int32 CmdRemoveFromRailroadStation(int x, int y, uint32 flags, uint32 p1, uint32
// make sure the specified tile belongs to the current player, and that it is a railroad station. // make sure the specified tile belongs to the current player, and that it is a railroad station.
if (!IS_TILETYPE(tile, MP_STATION) || _map5[tile] >= 8 || !_patches.nonuniform_stations) return CMD_ERROR; if (!IS_TILETYPE(tile, MP_STATION) || _map5[tile] >= 8 || !_patches.nonuniform_stations) return CMD_ERROR;
st = DEREF_STATION(_map2[tile]); st = GetStation(_map2[tile]);
if (_current_player != OWNER_WATER && (!CheckOwnership(st->owner) || !EnsureNoVehicle(tile))) return CMD_ERROR; if (_current_player != OWNER_WATER && (!CheckOwnership(st->owner) || !EnsureNoVehicle(tile))) return CMD_ERROR;
// if we reached here, it means we can actually delete it. do that. // if we reached here, it means we can actually delete it. do that.
@ -1225,7 +1228,7 @@ int32 DoConvertStationRail(uint tile, uint totype, bool exec)
{ {
Station *st; Station *st;
st = DEREF_STATION(_map2[tile]); st = GetStation(_map2[tile]);
if (!CheckOwnership(st->owner) || !EnsureNoVehicle(tile)) return CMD_ERROR; if (!CheckOwnership(st->owner) || !EnsureNoVehicle(tile)) return CMD_ERROR;
// tile is not a railroad station? // tile is not a railroad station?
@ -1967,7 +1970,7 @@ static void DrawTile_Station(TileInfo *ti)
//debug("Cust-o-mized %p", statspec); //debug("Cust-o-mized %p", statspec);
if (statspec != NULL) { if (statspec != NULL) {
Station *st = DEREF_STATION(_map2[ti->tile]); Station *st = GetStation(_map2[ti->tile]);
relocation = GetCustomStationRelocation(statspec, st, 0); relocation = GetCustomStationRelocation(statspec, st, 0);
//debug("Relocation %d", relocation); //debug("Relocation %d", relocation);
@ -2052,7 +2055,7 @@ static void GetTileDesc_Station(uint tile, TileDesc *td)
StringID str; StringID str;
td->owner = _map_owner[tile]; td->owner = _map_owner[tile];
td->build_date = DEREF_STATION(_map2[tile])->build_date; td->build_date = GetStation(_map2[tile])->build_date;
m5 = _map5[tile]; m5 = _map5[tile];
(str=STR_305E_RAILROAD_STATION, m5 < 8) || (str=STR_305E_RAILROAD_STATION, m5 < 8) ||
@ -2207,7 +2210,7 @@ static uint32 VehicleEnter_Station(Vehicle *v, uint tile, int x, int y)
} }
} else if (v->type == VEH_Road) { } else if (v->type == VEH_Road) {
if (v->u.road.state < 16 && (v->u.road.state&4)==0 && v->u.road.frame==0) { if (v->u.road.state < 16 && (v->u.road.state&4)==0 && v->u.road.frame==0) {
Station *st = DEREF_STATION(_map2[tile]); Station *st = GetStation(_map2[tile]);
byte m5 = _map5[tile]; byte m5 = _map5[tile];
byte *b, bb,state; byte *b, bb,state;
@ -2327,7 +2330,7 @@ static void UpdateStationRating(Station *st)
{ {
byte days = ge->days_since_pickup; byte days = ge->days_since_pickup;
if (st->last_vehicle != INVALID_VEHICLE && if (st->last_vehicle != INVALID_VEHICLE &&
(&_vehicles[st->last_vehicle])->type == VEH_Ship) GetVehicle(st->last_vehicle)->type == VEH_Ship)
days >>= 2; days >>= 2;
(days > 21) || (days > 21) ||
(rating += 25, days > 12) || (rating += 25, days > 12) ||
@ -2408,10 +2411,10 @@ void OnTick_Station()
return; return;
i = _station_tick_ctr; i = _station_tick_ctr;
if (++_station_tick_ctr == lengthof(_stations)) if (++_station_tick_ctr == _stations_size)
_station_tick_ctr = 0; _station_tick_ctr = 0;
st = DEREF_STATION(i); st = GetStation(i);
if (st->xy != 0) if (st->xy != 0)
StationHandleBigTick(st); StationHandleBigTick(st);
@ -2466,7 +2469,7 @@ int32 CmdRenameStation(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return CMD_ERROR; return CMD_ERROR;
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
st = DEREF_STATION(p1); st = GetStation(p1);
old_str = st->string_id; old_str = st->string_id;
st->string_id = str; st->string_id = str;
UpdateStationVirtCoord(st); UpdateStationVirtCoord(st);
@ -2520,7 +2523,7 @@ uint MoveGoodsToStation(uint tile, int w, int h, int type, uint amount)
st_index = _map2[cur_tile]; st_index = _map2[cur_tile];
for(i=0; i!=8; i++) { for(i=0; i!=8; i++) {
if (around[i] == 0xFF) { if (around[i] == 0xFF) {
st = DEREF_STATION(st_index); st = GetStation(st_index);
if ((st->had_vehicle_of_type & HVOT_BUOY) == 0 && if ((st->had_vehicle_of_type & HVOT_BUOY) == 0 &&
( !st->town->exclusive_counter || (st->town->exclusivity == st->owner) ) && // check exclusive transport rights ( !st->town->exclusive_counter || (st->town->exclusivity == st->owner) ) && // check exclusive transport rights
st->goods[type].rating != 0 && st->goods[type].rating != 0 &&
@ -2673,7 +2676,7 @@ void BuildOilRig(uint tile)
void DeleteOilRig(uint tile) void DeleteOilRig(uint tile)
{ {
Station *st = DEREF_STATION(_map2[tile]); Station *st = GetStation(_map2[tile]);
DoClearSquare(tile); DoClearSquare(tile);
@ -2691,7 +2694,7 @@ static void ChangeTileOwner_Station(uint tile, byte old_player, byte new_player)
return; return;
if (new_player != 255) { if (new_player != 255) {
Station *st = DEREF_STATION(_map2[tile]); Station *st = GetStation(_map2[tile]);
_map_owner[tile] = new_player; _map_owner[tile] = new_player;
st->owner = new_player; st->owner = new_player;
_global_station_sort_dirty = true; // transfer ownership of station to another player _global_station_sort_dirty = true; // transfer ownership of station to another player
@ -2716,7 +2719,7 @@ static int32 ClearTile_Station(uint tile, byte flags) {
return_cmd_error(STR_4800_IN_THE_WAY); return_cmd_error(STR_4800_IN_THE_WAY);
} }
st = DEREF_STATION(_map2[tile]); st = GetStation(_map2[tile]);
if (m5 < 8) if (m5 < 8)
return RemoveRailroadStation(st, tile, flags); return RemoveRailroadStation(st, tile, flags);
@ -2744,10 +2747,13 @@ static int32 ClearTile_Station(uint tile, byte flags) {
void InitializeStations() void InitializeStations()
{ {
int i; int i;
Station *s;
memset(_stations, 0, sizeof(_stations)); memset(_stations, 0, sizeof(_stations[0]) * _stations_size);
for(i = 0; i != lengthof(_stations); i++)
_stations[i].index=i; i = 0;
FOR_ALL_STATIONS(s)
s->index = i++;
_station_tick_ctr = 0; _station_tick_ctr = 0;
@ -2843,7 +2849,7 @@ static void SaveLoad_STNS(Station *st)
static void Save_STNS() static void Save_STNS()
{ {
Station *st; Station *st;
// Write the vehicles // Write the stations
FOR_ALL_STATIONS(st) { FOR_ALL_STATIONS(st) {
if (st->xy != 0) { if (st->xy != 0) {
SlSetArrayIndex(st->index); SlSetArrayIndex(st->index);
@ -2856,7 +2862,8 @@ static void Load_STNS()
{ {
int index; int index;
while ((index = SlIterateArray()) != -1) { while ((index = SlIterateArray()) != -1) {
Station *st = &_stations[index]; Station *st = GetStation(index);
SaveLoad_STNS(st); SaveLoad_STNS(st);
// this means it's an oldstyle savegame without support for nonuniform stations // this means it's an oldstyle savegame without support for nonuniform stations
@ -2868,6 +2875,11 @@ static void Load_STNS()
st->trainst_h = h; st->trainst_h = h;
} }
} }
/* This is to ensure all pointers are within the limits of
_stations_size */
if (_station_tick_ctr > _stations_size)
_station_tick_ctr = 0;
} }
const ChunkHandler _station_chunk_handlers[] = { const ChunkHandler _station_chunk_handlers[] = {

View File

@ -45,7 +45,6 @@ static void StationsWndShowStationRating(int x, int y, int type, uint acceptance
} }
} }
static SortStruct _station_sort[lengthof(_stations)];
static uint16 _num_station_sort[MAX_PLAYERS]; static uint16 _num_station_sort[MAX_PLAYERS];
static char _bufcache[64]; static char _bufcache[64];
@ -58,14 +57,14 @@ static int CDECL StationNameSorter(const void *a, const void *b)
const SortStruct *cmp1 = (const SortStruct*)a; const SortStruct *cmp1 = (const SortStruct*)a;
const SortStruct *cmp2 = (const SortStruct*)b; const SortStruct *cmp2 = (const SortStruct*)b;
st = DEREF_STATION(cmp1->index); st = GetStation(cmp1->index);
SetDParam(0, st->town->townnametype); SetDParam(0, st->town->townnametype);
SetDParam(1, st->town->townnameparts); SetDParam(1, st->town->townnameparts);
GetString(buf1, st->string_id); GetString(buf1, st->string_id);
if ( cmp2->index != _last_station_idx) { if ( cmp2->index != _last_station_idx) {
_last_station_idx = cmp2->index; _last_station_idx = cmp2->index;
st = DEREF_STATION(cmp2->index); st = GetStation(cmp2->index);
SetDParam(0, st->town->townnametype); SetDParam(0, st->town->townnametype);
SetDParam(1, st->town->townnameparts); SetDParam(1, st->town->townnameparts);
GetString(_bufcache, st->string_id); GetString(_bufcache, st->string_id);
@ -81,7 +80,13 @@ static void GlobalSortStationList()
uint16 *i; uint16 *i;
// reset #-of stations to 0 because ++ is used for value-assignment // reset #-of stations to 0 because ++ is used for value-assignment
for (i = _num_station_sort; i != endof(_num_station_sort); i++) {*i = 0;} for (i = _num_station_sort; i != endof(_num_station_sort); i++)
*i = 0;
/* Create array for sorting */
_station_sort = realloc(_station_sort, _stations_size * sizeof(_station_sort[0]));
if (_station_sort == NULL)
error("Could not allocate memory for the station-sorting-list");
FOR_ALL_STATIONS(st) { FOR_ALL_STATIONS(st) {
if(st->xy && st->owner != OWNER_NONE) { if(st->xy && st->owner != OWNER_NONE) {
@ -171,7 +176,7 @@ static void PlayerStationsWndProc(Window *w, WindowEvent *e)
assert(i < _num_station_sort[window_number]); // at least one station must exist assert(i < _num_station_sort[window_number]); // at least one station must exist
while (i < _num_station_sort[window_number]) { // do until max number of stations of owner while (i < _num_station_sort[window_number]) { // do until max number of stations of owner
st = DEREF_STATION(_station_sort[i].index); st = GetStation(_station_sort[i].index);
assert(st->xy && st->owner == window_number); assert(st->xy && st->owner == window_number);
@ -209,7 +214,7 @@ static void PlayerStationsWndProc(Window *w, WindowEvent *e)
if (id_v >= _num_station_sort[owner]) { return;} // click out of station bound if (id_v >= _num_station_sort[owner]) { return;} // click out of station bound
st = DEREF_STATION(_station_sort[id_v].index); st = GetStation(_station_sort[id_v].index);
assert(st->xy && st->owner == owner); assert(st->xy && st->owner == owner);
@ -315,7 +320,7 @@ static void DrawStationViewWindow(Window *w)
station_id = (byte)w->window_number; station_id = (byte)w->window_number;
st = DEREF_STATION(w->window_number); st = GetStation(w->window_number);
num = 1; num = 1;
for(i=0; i!=NUM_CARGO; i++) { for(i=0; i!=NUM_CARGO; i++) {
@ -449,7 +454,7 @@ static void StationViewWndProc(Window *w, WindowEvent *e)
case WE_CLICK: case WE_CLICK:
switch(e->click.widget) { switch(e->click.widget) {
case 7: case 7:
ScrollMainWindowToTile(DEREF_STATION(w->window_number)->xy); ScrollMainWindowToTile(GetStation(w->window_number)->xy);
break; break;
case 8: case 8:
@ -468,32 +473,32 @@ static void StationViewWndProc(Window *w, WindowEvent *e)
break; break;
case 9: { case 9: {
Station *st = DEREF_STATION(w->window_number); Station *st = GetStation(w->window_number);
SetDParam(0, st->town->townnametype); SetDParam(0, st->town->townnametype);
SetDParam(1, st->town->townnameparts); SetDParam(1, st->town->townnameparts);
ShowQueryString(st->string_id, STR_3030_RENAME_STATION_LOADING, 31, 180, w->window_class, w->window_number); ShowQueryString(st->string_id, STR_3030_RENAME_STATION_LOADING, 31, 180, w->window_class, w->window_number);
} break; } break;
case 10: { case 10: {
const Station *st = DEREF_STATION(w->window_number); const Station *st = GetStation(w->window_number);
ShowPlayerTrains(st->owner, w->window_number); ShowPlayerTrains(st->owner, w->window_number);
break; break;
} }
case 11: { case 11: {
const Station *st = DEREF_STATION(w->window_number); const Station *st = GetStation(w->window_number);
ShowPlayerRoadVehicles(st->owner, w->window_number); ShowPlayerRoadVehicles(st->owner, w->window_number);
break; break;
} }
case 12: { case 12: {
const Station *st = DEREF_STATION(w->window_number); const Station *st = GetStation(w->window_number);
ShowPlayerAircraft(st->owner, w->window_number); ShowPlayerAircraft(st->owner, w->window_number);
break; break;
} }
case 13: { case 13: {
const Station *st = DEREF_STATION(w->window_number); const Station *st = GetStation(w->window_number);
ShowPlayerShips(st->owner, w->window_number); ShowPlayerShips(st->owner, w->window_number);
break; break;
} }
@ -507,13 +512,13 @@ static void StationViewWndProc(Window *w, WindowEvent *e)
return; return;
memcpy(_decode_parameters, b, 32); memcpy(_decode_parameters, b, 32);
st = DEREF_STATION(w->window_number); st = GetStation(w->window_number);
DoCommandP(st->xy, w->window_number, 0, NULL, CMD_RENAME_STATION | CMD_MSG(STR_3031_CAN_T_RENAME_STATION)); DoCommandP(st->xy, w->window_number, 0, NULL, CMD_RENAME_STATION | CMD_MSG(STR_3031_CAN_T_RENAME_STATION));
} break; } break;
case WE_DESTROY: { case WE_DESTROY: {
WindowNumber wno = WindowNumber wno =
(w->window_number << 16) | DEREF_STATION(w->window_number)->owner; (w->window_number << 16) | GetStation(w->window_number)->owner;
DeleteWindowById(WC_TRAINS_LIST, wno); DeleteWindowById(WC_TRAINS_LIST, wno);
DeleteWindowById(WC_ROADVEH_LIST, wno); DeleteWindowById(WC_ROADVEH_LIST, wno);
@ -540,7 +545,7 @@ void ShowStationViewWindow(int station)
w = AllocateWindowDescFront(&_station_view_desc, station); w = AllocateWindowDescFront(&_station_view_desc, station);
if (w) { if (w) {
color = DEREF_STATION(w->window_number)->owner; color = GetStation(w->window_number)->owner;
if (color != 0x10) if (color != 0x10)
w->caption_color = color; w->caption_color = color;
w->vscroll.cap = 5; w->vscroll.cap = 5;

View File

@ -432,7 +432,7 @@ static byte *DecodeString(byte *buff, const byte *str)
case 0x9A: { // {STATION} case 0x9A: { // {STATION}
Station *st; Station *st;
InjectDparam(1); InjectDparam(1);
st = DEREF_STATION(GetDParam(1)); st = GetStation(GetDParam(1));
if (!st->xy) { // station doesn't exist anymore if (!st->xy) { // station doesn't exist anymore
buff = GetString(buff, STR_UNKNOWN_DESTINATION); buff = GetString(buff, STR_UNKNOWN_DESTINATION);
break; break;
@ -444,7 +444,7 @@ static byte *DecodeString(byte *buff, const byte *str)
} }
case 0x9B: { // {TOWN} case 0x9B: { // {TOWN}
Town *t; Town *t;
t = DEREF_TOWN(GetDParam(0)); t = GetTown(GetDParam(0));
assert(t->xy); assert(t->xy);
SetDParam(0, t->townnameparts); SetDParam(0, t->townnameparts);
buff = GetString(buff, t->townnametype); buff = GetString(buff, t->townnametype);

View File

@ -49,22 +49,22 @@ handle_click:
/* determine from coordinate for subsidy and try to scroll to it */ /* determine from coordinate for subsidy and try to scroll to it */
offs = s->from; offs = s->from;
if (s->age >= 12) { if (s->age >= 12) {
xy = DEREF_STATION(offs)->xy; xy = GetStation(offs)->xy;
} else if (s->cargo_type == CT_PASSENGERS || s->cargo_type == CT_MAIL) { } else if (s->cargo_type == CT_PASSENGERS || s->cargo_type == CT_MAIL) {
xy = DEREF_TOWN(offs)->xy; xy = GetTown(offs)->xy;
} else { } else {
xy = _industries[offs].xy; xy = GetIndustry(offs)->xy;
} }
if (!ScrollMainWindowToTile(xy)) { if (!ScrollMainWindowToTile(xy)) {
/* otherwise determine to coordinate for subsidy and scroll to it */ /* otherwise determine to coordinate for subsidy and scroll to it */
offs = s->to; offs = s->to;
if (s->age >= 12) { if (s->age >= 12) {
xy = DEREF_STATION(offs)->xy; xy = GetStation(offs)->xy;
} else if (s->cargo_type == CT_PASSENGERS || s->cargo_type == CT_MAIL || s->cargo_type == CT_GOODS || s->cargo_type == CT_FOOD) { } else if (s->cargo_type == CT_PASSENGERS || s->cargo_type == CT_MAIL || s->cargo_type == CT_GOODS || s->cargo_type == CT_FOOD) {
xy = DEREF_TOWN(offs)->xy; xy = GetTown(offs)->xy;
} else { } else {
xy = _industries[offs].xy; xy = GetIndustry(offs)->xy;
} }
ScrollMainWindowToTile(xy); ScrollMainWindowToTile(xy);
} }
@ -112,7 +112,7 @@ static void DrawSubsidiesWindow(Window *w)
if (s->cargo_type != 0xFF && s->age >= 12) { if (s->cargo_type != 0xFF && s->age >= 12) {
SetupSubsidyDecodeParam(s, 1); SetupSubsidyDecodeParam(s, 1);
p = DEREF_PLAYER(DEREF_STATION(s->to)->owner); p = DEREF_PLAYER(GetStation(s->to)->owner);
SetDParam(3, p->name_1); SetDParam(3, p->name_1);
SetDParam(4, p->name_2); SetDParam(4, p->name_2);

15
town.h
View File

@ -91,10 +91,19 @@ enum {
bool CheckforTownRating(uint tile, uint32 flags, Town *t, byte type); bool CheckforTownRating(uint tile, uint32 flags, Town *t, byte type);
#define DEREF_TOWN(i) (&_towns[i])
#define FOR_ALL_TOWNS(c) for(c=_towns; c != endof(_towns); c++)
VARDEF Town _towns[70]; VARDEF Town _towns[70];
VARDEF uint _towns_size;
VARDEF uint16 *_town_sort;
static inline Town *GetTown(uint index)
{
assert(index < _towns_size);
return &_towns[index];
}
#define FOR_ALL_TOWNS(t) for(t = _towns; t != &_towns[_towns_size]; t++)
VARDEF int _total_towns; // For the AI: the amount of towns active VARDEF int _total_towns; // For the AI: the amount of towns active
VARDEF bool _town_sort_dirty; VARDEF bool _town_sort_dirty;

View File

@ -401,8 +401,8 @@ void OnTick_Town()
return; return;
i = _cur_town_ctr; i = _cur_town_ctr;
t = DEREF_TOWN(i); t = GetTown(i);
if (++i == lengthof(_towns)) i = 0; if (++i == _towns_size) i = 0;
_cur_town_ctr = i; _cur_town_ctr = i;
if (t->xy != 0) if (t->xy != 0)
@ -1354,7 +1354,7 @@ static void ClearTownHouse(Town *t, uint tile) {
int32 CmdRenameTown(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 CmdRenameTown(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
StringID str; StringID str;
Town *t = DEREF_TOWN(p1); Town *t = GetTown(p1);
str = AllocateNameUnique((byte*)_decode_parameters, 4); str = AllocateNameUnique((byte*)_decode_parameters, 4);
if (str == 0) if (str == 0)
@ -1602,7 +1602,7 @@ int32 CmdDoTownAction(int x, int y, uint32 flags, uint32 p1, uint32 p2)
cost = (_price.build_industry >> 8) * _town_action_costs[p2]; cost = (_price.build_industry >> 8) * _town_action_costs[p2];
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
_town_action_proc[p2](DEREF_TOWN(p1), p2); _town_action_proc[p2](GetTown(p1), p2);
InvalidateWindow(WC_TOWN_AUTHORITY, p1); InvalidateWindow(WC_TOWN_AUTHORITY, p1);
} }
@ -1817,11 +1817,14 @@ void TownsMonthlyLoop()
void InitializeTowns() void InitializeTowns()
{ {
Subsidy *s; Subsidy *s;
Town *t;
int i; int i;
memset(_towns, 0, sizeof(_towns)); memset(_towns, 0, sizeof(_towns[0]) * _towns_size);
for(i=0; i!=lengthof(_towns); i++)
_towns[i].index = i; i = 0;
FOR_ALL_TOWNS(t)
t->index = i++;
memset(_subsidies, 0, sizeof(_subsidies)); memset(_subsidies, 0, sizeof(_subsidies));
for (s=_subsidies; s != endof(_subsidies); s++) for (s=_subsidies; s != endof(_subsidies); s++)
@ -1908,9 +1911,11 @@ static void Save_TOWN()
{ {
Town *t; Town *t;
FOR_ALL_TOWNS(t) if (t->xy != 0) { FOR_ALL_TOWNS(t) {
SlSetArrayIndex(t->index); if (t->xy != 0) {
SlObject(t, _town_desc); SlSetArrayIndex(t->index);
SlObject(t, _town_desc);
}
} }
} }
@ -1918,7 +1923,8 @@ static void Load_TOWN()
{ {
int index; int index;
while ((index = SlIterateArray()) != -1) { while ((index = SlIterateArray()) != -1) {
Town *t = DEREF_TOWN(index); Town *t = GetTown(index);
SlObject(t, _town_desc); SlObject(t, _town_desc);
if (index > _total_towns) _total_towns = index; if (index > _total_towns) _total_towns = index;
} }

View File

@ -85,7 +85,7 @@ static void TownAuthorityWndProc(Window *w, WindowEvent *e)
{ {
uint buttons; uint buttons;
int numact; int numact;
Town *t = DEREF_TOWN(w->window_number); Town *t = GetTown(w->window_number);
switch(e->event) { switch(e->event) {
case WE_PAINT: case WE_PAINT:
@ -224,7 +224,7 @@ static void ShowTownAuthorityWindow(uint town)
static void TownViewWndProc(Window *w, WindowEvent *e) static void TownViewWndProc(Window *w, WindowEvent *e)
{ {
Town *t = DEREF_TOWN(w->window_number); Town *t = GetTown(w->window_number);
switch(e->event) { switch(e->event) {
case WE_PAINT: case WE_PAINT:
@ -338,7 +338,7 @@ void ShowTownViewWindow(uint town)
if (w) { if (w) {
w->flags4 |= WF_DISABLE_VP_SCROLL; w->flags4 |= WF_DISABLE_VP_SCROLL;
t = DEREF_TOWN(w->window_number); t = GetTown(w->window_number);
AssignWindowViewport(w, 3, 17, 0xFE, 0x56, t->xy, 1); AssignWindowViewport(w, 3, 17, 0xFE, 0x56, t->xy, 1);
} }
} }
@ -357,7 +357,6 @@ static const Widget _town_directory_widgets[] = {
// used to get a sorted list of the towns // used to get a sorted list of the towns
static uint16 _town_sort[lengthof(_towns)];
static uint _num_town_sort; static uint _num_town_sort;
static char _bufcache[64]; static char _bufcache[64];
@ -370,13 +369,13 @@ static int CDECL TownNameSorter(const void *a, const void *b)
byte val; byte val;
int r; int r;
t = DEREF_TOWN(*(const uint16*)a); t = GetTown(*(const uint16*)a);
SetDParam(0, t->townnameparts); SetDParam(0, t->townnameparts);
GetString(buf1, t->townnametype); GetString(buf1, t->townnametype);
if ( (val=*(const uint16*)b) != _last_town_idx) { if ( (val=*(const uint16*)b) != _last_town_idx) {
_last_town_idx = val; _last_town_idx = val;
t = DEREF_TOWN(val); t = GetTown(val);
SetDParam(0, t->townnameparts); SetDParam(0, t->townnameparts);
GetString(_bufcache, t->townnametype); GetString(_bufcache, t->townnametype);
} }
@ -388,8 +387,8 @@ static int CDECL TownNameSorter(const void *a, const void *b)
static int CDECL TownPopSorter(const void *a, const void *b) static int CDECL TownPopSorter(const void *a, const void *b)
{ {
const Town *ta = DEREF_TOWN(*(const uint16*)a); const Town *ta = GetTown(*(const uint16*)a);
const Town *tb = DEREF_TOWN(*(const uint16*)b); const Town *tb = GetTown(*(const uint16*)b);
int r = ta->population - tb->population; int r = ta->population - tb->population;
if (_town_sort_order & 1) r = -r; if (_town_sort_order & 1) r = -r;
return r; return r;
@ -399,6 +398,12 @@ static void MakeSortedTownList()
{ {
Town *t; Town *t;
int n = 0; int n = 0;
/* Create array for sorting */
_town_sort = realloc(_town_sort, _towns_size * sizeof(_town_sort[0]));
if (_town_sort == NULL)
error("Could not allocate memory for the town-sorting-list");
FOR_ALL_TOWNS(t) FOR_ALL_TOWNS(t)
if(t->xy) if(t->xy)
_town_sort[n++] = t->index; _town_sort[n++] = t->index;
@ -434,7 +439,7 @@ static void TownDirectoryWndProc(Window *w, WindowEvent *e)
int y = 28; int y = 28;
while (i < _num_town_sort) { while (i < _num_town_sort) {
t = DEREF_TOWN(_town_sort[i]); t = GetTown(_town_sort[i]);
assert(t->xy); assert(t->xy);
@ -473,7 +478,7 @@ static void TownDirectoryWndProc(Window *w, WindowEvent *e)
if (id_v >= _num_town_sort) { return;} // click out of town bounds if (id_v >= _num_town_sort) { return;} // click out of town bounds
{ {
Town *t = DEREF_TOWN(_town_sort[id_v]); Town *t = GetTown(_town_sort[id_v]);
assert(t->xy); assert(t->xy);
ScrollMainWindowToTile(t->xy); ScrollMainWindowToTile(t->xy);

View File

@ -245,20 +245,16 @@ static int32 CmdBuildRailWagon(uint engine, uint tile, uint32 flags)
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
byte img = rvi->image_index; byte img = rvi->image_index;
Vehicle *u; Vehicle *u, *w;
v->spritenum = img; v->spritenum = img;
u = _vehicles; u = NULL;
for(;;) {
if (u->type == VEH_Train && u->tile == (TileIndex)tile &&
u->subtype == 4 && u->engine_type == engine) {
u = GetLastVehicleInChain(u);
break;
}
if (++u == endof(_vehicles)) { FOR_ALL_VEHICLES(w) {
u = NULL; if (w->type == VEH_Train && w->tile == (TileIndex)tile &&
w->subtype == 4 && w->engine_type == engine) {
u = GetLastVehicleInChain(w);
break; break;
} }
} }
@ -598,7 +594,7 @@ int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
Vehicle *src, *dst, *src_head, *dst_head; Vehicle *src, *dst, *src_head, *dst_head;
bool is_loco; bool is_loco;
src = &_vehicles[p1 & 0xffff]; src = GetVehicle(p1 & 0xFFFF);
if (src->type != VEH_Train) return CMD_ERROR; if (src->type != VEH_Train) return CMD_ERROR;
is_loco = !(RailVehInfo(src->engine_type)->flags & RVI_WAGON) is_loco = !(RailVehInfo(src->engine_type)->flags & RVI_WAGON)
@ -609,7 +605,7 @@ int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
dst = NULL; dst = NULL;
if (!is_loco) dst = FindGoodVehiclePos(src); if (!is_loco) dst = FindGoodVehiclePos(src);
} else { } else {
dst = &_vehicles[((int32)p1 >> 16)]; dst = GetVehicle(((int32)p1 >> 16));
} }
// don't move the same vehicle.. // don't move the same vehicle..
@ -746,7 +742,7 @@ int32 CmdStartStopTrain(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *v; Vehicle *v;
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner)) if (!CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -772,7 +768,7 @@ int32 CmdSellRailWagon(int x, int y, uint32 flags, uint32 p1, uint32 p2)
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner)) if (!CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -1018,7 +1014,7 @@ int32 CmdReverseTrainDirection(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *v; Vehicle *v;
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner)) if (!CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -1047,7 +1043,7 @@ int32 CmdForceTrainProceed(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *v; Vehicle *v;
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner)) if (!CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -1073,7 +1069,7 @@ int32 CmdRefitRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
SET_EXPENSES_TYPE(EXPENSES_TRAIN_RUN); SET_EXPENSES_TYPE(EXPENSES_TRAIN_RUN);
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner) || ((CheckStoppedInDepot(v) < 0) && !(SkipStoppedInDepotCheck))) if (!CheckOwnership(v->owner) || ((CheckStoppedInDepot(v) < 0) && !(SkipStoppedInDepotCheck)))
return CMD_ERROR; return CMD_ERROR;
@ -1182,7 +1178,7 @@ static TrainFindDepotData FindClosestTrainDepot(Vehicle *v)
int32 CmdTrainGotoDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 CmdTrainGotoDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *v = &_vehicles[p1]; Vehicle *v = GetVehicle(p1);
TrainFindDepotData tfdd; TrainFindDepotData tfdd;
if (v->current_order.type == OT_GOTO_DEPOT) { if (v->current_order.type == OT_GOTO_DEPOT) {
@ -1219,7 +1215,7 @@ int32 CmdTrainGotoDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2)
*/ */
int32 CmdChangeTrainServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 CmdChangeTrainServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{ {
Vehicle *v = &_vehicles[p1]; Vehicle *v = GetVehicle(p1);
if (!CheckOwnership(v->owner)) if (!CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -1677,7 +1673,7 @@ static bool ProcessTrainOrder(Vehicle *v)
if (order.type == OT_GOTO_STATION) { if (order.type == OT_GOTO_STATION) {
if (order.station == v->last_station_visited) if (order.station == v->last_station_visited)
v->last_station_visited = 0xFFFF; v->last_station_visited = 0xFFFF;
v->dest_tile = DEREF_STATION(order.station)->xy; v->dest_tile = GetStation(order.station)->xy;
result = CheckReverseTrain(v); result = CheckReverseTrain(v);
} else if (order.type == OT_GOTO_DEPOT) { } else if (order.type == OT_GOTO_DEPOT) {
v->dest_tile = _depots[order.station].xy; v->dest_tile = _depots[order.station].xy;
@ -1783,7 +1779,7 @@ static void TrainEnterStation(Vehicle *v, int station)
v->last_station_visited = station; v->last_station_visited = station;
/* check if a train ever visited this station before */ /* check if a train ever visited this station before */
st = DEREF_STATION(station); st = GetStation(station);
if (!(st->had_vehicle_of_type & HVOT_TRAIN)) { if (!(st->had_vehicle_of_type & HVOT_TRAIN)) {
st->had_vehicle_of_type |= HVOT_TRAIN; st->had_vehicle_of_type |= HVOT_TRAIN;
SetDParam(0, st->index); SetDParam(0, st->index);
@ -2608,7 +2604,7 @@ static const byte _depot_track_ind[4] = {0,1,0,1};
// Validation for the news item "Train is waiting in depot" // Validation for the news item "Train is waiting in depot"
bool ValidateTrainInDepot( uint data_a, uint data_b ) bool ValidateTrainInDepot( uint data_a, uint data_b )
{ {
Vehicle *v = &_vehicles[data_a]; Vehicle *v = GetVehicle(data_a);
if (v->u.rail.track == 0x80 && (v->vehstatus | VS_STOPPED)) if (v->u.rail.track == 0x80 && (v->vehstatus | VS_STOPPED))
return true; return true;
else else
@ -2752,7 +2748,7 @@ void OnNewDay_Train(Vehicle *v)
/* update destination */ /* update destination */
if (v->current_order.type == OT_GOTO_STATION && if (v->current_order.type == OT_GOTO_STATION &&
(tile = DEREF_STATION(v->current_order.station)->train_tile) != 0) (tile = GetStation(v->current_order.station)->train_tile) != 0)
v->dest_tile = tile; v->dest_tile = tile;
if ((v->vehstatus & VS_STOPPED) == 0) { if ((v->vehstatus & VS_STOPPED) == 0) {

View File

@ -90,7 +90,7 @@ void CcBuildLoco(bool success, uint tile, uint32 p1, uint32 p2)
if (!success) if (!success)
return; return;
v = &_vehicles[_new_train_id]; v = GetVehicle(_new_train_id);
if (tile == _backup_orders_tile) { if (tile == _backup_orders_tile) {
_backup_orders_tile = 0; _backup_orders_tile = 0;
RestoreVehicleOrders(v, _backup_orders_data); RestoreVehicleOrders(v, _backup_orders_data);
@ -458,7 +458,7 @@ static void TrainDepotMoveVehicle(Vehicle *wagon, int sel, Vehicle *head)
{ {
Vehicle *v; Vehicle *v;
v = &_vehicles[sel]; v = GetVehicle(sel);
if (/*v->subtype == 0 ||*/ v == wagon) if (/*v->subtype == 0 ||*/ v == wagon)
return; return;
@ -553,7 +553,7 @@ static void TrainDepotWndProc(Window *w, WindowEvent *e)
if (WP(w,traindepot_d).sel == INVALID_VEHICLE) if (WP(w,traindepot_d).sel == INVALID_VEHICLE)
return; return;
v = &_vehicles[WP(w,traindepot_d).sel]; v = GetVehicle(WP(w,traindepot_d).sel);
WP(w,traindepot_d).sel = INVALID_VEHICLE; WP(w,traindepot_d).sel = INVALID_VEHICLE;
SetWindowDirty(w); SetWindowDirty(w);
@ -658,7 +658,7 @@ static void RailVehicleRefitWndProc(Window *w, WindowEvent *e)
{ {
switch(e->event) { switch(e->event) {
case WE_PAINT: { case WE_PAINT: {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
const byte *b; const byte *b;
int sel; int sel;
int x,y; int x,y;
@ -734,7 +734,7 @@ static void RailVehicleRefitWndProc(Window *w, WindowEvent *e)
} break; } break;
case 4: /* refit button */ case 4: /* refit button */
if (WP(w,refit_d).cargo != 0xFF) { if (WP(w,refit_d).cargo != 0xFF) {
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_RAIL_VEHICLE | CMD_MSG(STR_RAIL_CAN_T_REFIT_VEHICLE))) if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_RAIL_VEHICLE | CMD_MSG(STR_RAIL_CAN_T_REFIT_VEHICLE)))
DeleteWindow(w); DeleteWindow(w);
} }
@ -797,7 +797,7 @@ static void TrainViewWndProc(Window *w, WindowEvent *e)
Vehicle *v; Vehicle *v;
StringID str; StringID str;
v = &_vehicles[w->window_number]; v = GetVehicle(w->window_number);
w->disabled_state = (v->owner == _local_player) ? 0 : 0x380; w->disabled_state = (v->owner == _local_player) ? 0 : 0x380;
@ -864,7 +864,7 @@ static void TrainViewWndProc(Window *w, WindowEvent *e)
case WE_CLICK: { case WE_CLICK: {
int wid = e->click.widget; int wid = e->click.widget;
Vehicle *v = &_vehicles[w->window_number]; Vehicle *v = GetVehicle(w->window_number);
switch(wid) { switch(wid) {
case 5: /* start/stop train */ case 5: /* start/stop train */
@ -905,7 +905,7 @@ static void TrainViewWndProc(Window *w, WindowEvent *e)
Vehicle *v; Vehicle *v;
uint32 h; uint32 h;
v = &_vehicles[w->window_number]; v = GetVehicle(w->window_number);
assert(v->type == VEH_Train); assert(v->type == VEH_Train);
h = CheckStoppedInDepot(v) >= 0 ? (1 << 9) : (1 << 12); h = CheckStoppedInDepot(v) >= 0 ? (1 << 9) : (1 << 12);
if (h != w->hidden_state) { if (h != w->hidden_state) {
@ -1003,7 +1003,7 @@ static void DrawTrainDetailsWindow(Window *w)
if (det_tab == 3) // reset tot_cargo array to 0 values if (det_tab == 3) // reset tot_cargo array to 0 values
memset(tot_cargo, 0, sizeof(tot_cargo)); memset(tot_cargo, 0, sizeof(tot_cargo));
u = v = &_vehicles[w->window_number]; u = v = GetVehicle(w->window_number);
do { do {
if (det_tab != 3) if (det_tab != 3)
num++; num++;
@ -1114,7 +1114,7 @@ static void TrainDetailsWndProc(Window *w, WindowEvent *e)
Vehicle *v; Vehicle *v;
switch(e->click.widget) { switch(e->click.widget) {
case 2: /* name train */ case 2: /* name train */
v = &_vehicles[w->window_number]; v = GetVehicle(w->window_number);
SetDParam(0, v->unitnumber); SetDParam(0, v->unitnumber);
ShowQueryString(v->string_id, STR_8865_NAME_TRAIN, 31, 150, w->window_class, w->window_number); ShowQueryString(v->string_id, STR_8865_NAME_TRAIN, 31, 150, w->window_class, w->window_number);
break; break;
@ -1125,7 +1125,7 @@ static void TrainDetailsWndProc(Window *w, WindowEvent *e)
case 7: /* dec serv interval */ case 7: /* dec serv interval */
mod = _ctrl_pressed? -5 : -10; mod = _ctrl_pressed? -5 : -10;
do_change_service_int: do_change_service_int:
v = &_vehicles[w->window_number]; v = GetVehicle(w->window_number);
mod += v->service_interval; mod += v->service_interval;
/* %-based service interval max 5%-90% /* %-based service interval max 5%-90%
@ -1276,7 +1276,7 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e)
w->widget[1].unkA = STR_881B_TRAINS; w->widget[1].unkA = STR_881B_TRAINS;
} else { } else {
/* Station Name -- (###) Trains */ /* Station Name -- (###) Trains */
SetDParam(0, DEREF_STATION(station)->index); SetDParam(0, GetStation(station)->index);
SetDParam(1, w->vscroll.count); SetDParam(1, w->vscroll.count);
w->widget[1].unkA = STR_SCHEDULED_TRAINS; w->widget[1].unkA = STR_SCHEDULED_TRAINS;
} }
@ -1290,7 +1290,7 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e)
max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length); max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length);
for (i = w->vscroll.pos; i < max; ++i) { for (i = w->vscroll.pos; i < max; ++i) {
Vehicle *v = DEREF_VEHICLE(vl->sort_list[i].index); Vehicle *v = GetVehicle(vl->sort_list[i].index);
StringID str; StringID str;
assert(v->type == VEH_Train && v->owner == owner); assert(v->type == VEH_Train && v->owner == owner);
@ -1344,7 +1344,7 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e)
if (id_v >= vl->list_length) return; // click out of list bound if (id_v >= vl->list_length) return; // click out of list bound
v = DEREF_VEHICLE(vl->sort_list[id_v].index); v = GetVehicle(vl->sort_list[id_v].index);
assert(v->type == VEH_Train && v->subtype == 0 && v->owner == owner); assert(v->type == VEH_Train && v->subtype == 0 && v->owner == owner);

35
ttd.c
View File

@ -482,6 +482,35 @@ void ParseResolution(int res[2], char *s)
res[1] = strtoul(t + 1, NULL, 0); res[1] = strtoul(t + 1, NULL, 0);
} }
static void InitializeDynamicVariables(void)
{
/* Dynamic stuff needs to be initialized somewhere... */
_stations_size = lengthof(_stations);
_station_sort = NULL;
_vehicles_size = lengthof(_vehicles);
_vehicle_sort = NULL;
_towns_size = lengthof(_towns);
_town_sort = NULL;
_industries_size = lengthof(_industries);
_industry_sort = NULL;
}
static void UnInitializeDynamicVariables(void)
{
/* Dynamic stuff needs to be free'd somewhere... */
free(_station_sort);
free(_vehicle_sort);
free(_town_sort);
free(_industry_sort);
}
void LoadIntroGame() void LoadIntroGame()
{ {
char filename[256]; char filename[256];
@ -640,6 +669,9 @@ int ttd_main(int argc, char* argv[])
// initialize airport state machines // initialize airport state machines
InitializeAirports(); InitializeAirports();
/* initialize all variables that are allocated dynamically */
InitializeDynamicVariables();
// Sample catalogue // Sample catalogue
DEBUG(misc, 1) ("Loading sound effects..."); DEBUG(misc, 1) ("Loading sound effects...");
_os_version = GetOSVersion(); _os_version = GetOSVersion();
@ -721,6 +753,9 @@ int ttd_main(int argc, char* argv[])
// uninitialize airport state machines // uninitialize airport state machines
UnInitializeAirports(); UnInitializeAirports();
/* uninitialize variables that are allocated dynamic */
UnInitializeDynamicVariables();
return 0; return 0;
} }

View File

@ -15,6 +15,10 @@
#define INVALID_COORD (-0x8000) #define INVALID_COORD (-0x8000)
#define GEN_HASH(x,y) (((x & 0x1F80)>>7) + ((y & 0xFC0))) #define GEN_HASH(x,y) (((x & 0x1F80)>>7) + ((y & 0xFC0)))
enum {
VEHICLES_MIN_FREE_FOR_AI = 90
};
void VehicleServiceInDepot(Vehicle *v) void VehicleServiceInDepot(Vehicle *v)
{ {
v->date_of_last_service = _date; v->date_of_last_service = _date;
@ -106,14 +110,13 @@ Vehicle *FindVehicleBetween(TileIndex from, TileIndex to, byte z)
int x2 = GET_TILE_X(to); int x2 = GET_TILE_X(to);
int y2 = GET_TILE_Y(to); int y2 = GET_TILE_Y(to);
Vehicle *veh; Vehicle *veh;
uint count;
/* Make sure x1 < x2 or y1 < y2 */ /* Make sure x1 < x2 or y1 < y2 */
if (x1 > x2 || y1 > y2) { if (x1 > x2 || y1 > y2) {
intswap(x1,x2); intswap(x1,x2);
intswap(y1,y2); intswap(y1,y2);
} }
for(veh = _vehicles, count=lengthof(_vehicles); count != 0; count--, veh++) { FOR_ALL_VEHICLES(veh) {
if ((veh->type == VEH_Train || veh->type == VEH_Road) && (z==0xFF || veh->z_pos == z)) { if ((veh->type == VEH_Train || veh->type == VEH_Road) && (z==0xFF || veh->z_pos == z)) {
if ((veh->x_pos>>4) >= x1 && (veh->x_pos>>4) <= x2 && if ((veh->x_pos>>4) >= x1 && (veh->x_pos>>4) <= x2 &&
(veh->y_pos>>4) >= y1 && (veh->y_pos>>4) <= y2) { (veh->y_pos>>4) >= y1 && (veh->y_pos>>4) <= y2) {
@ -212,8 +215,7 @@ static Vehicle *InitializeVehicle(Vehicle *v)
Vehicle *ForceAllocateSpecialVehicle() Vehicle *ForceAllocateSpecialVehicle()
{ {
Vehicle *v; Vehicle *v;
for(v=_vehicles + NUM_NORMAL_VEHICLES; FOR_ALL_VEHICLES_FROM(v, NUM_NORMAL_VEHICLES) {
v!=&_vehicles[NUM_NORMAL_VEHICLES+NUM_SPECIAL_VEHICLES]; v++) {
if (v->type == 0) if (v->type == 0)
return InitializeVehicle(v); return InitializeVehicle(v);
} }
@ -224,7 +226,10 @@ Vehicle *ForceAllocateSpecialVehicle()
Vehicle *ForceAllocateVehicle() Vehicle *ForceAllocateVehicle()
{ {
Vehicle *v; Vehicle *v;
for(v=_vehicles; v!=&_vehicles[NUM_NORMAL_VEHICLES]; v++) { FOR_ALL_VEHICLES(v) {
if (v->index >= NUM_NORMAL_VEHICLES)
return NULL;
if (v->type == 0) if (v->type == 0)
return InitializeVehicle(v); return InitializeVehicle(v);
} }
@ -239,12 +244,15 @@ Vehicle *AllocateVehicle()
if (IS_HUMAN_PLAYER(_current_player)) { if (IS_HUMAN_PLAYER(_current_player)) {
num = 0; num = 0;
for(v=_vehicles; v!=&_vehicles[NUM_NORMAL_VEHICLES]; v++) { FOR_ALL_VEHICLES(v) {
if (v->index >= NUM_NORMAL_VEHICLES)
break;
if (v->type == 0) if (v->type == 0)
num++; num++;
} }
if (num <= 90) if (num <= VEHICLES_MIN_FREE_FOR_AI)
return NULL; return NULL;
} }
@ -268,7 +276,7 @@ void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
for(;;) { for(;;) {
veh = _vehicle_position_hash[ (x+y)&0xFFFF ]; veh = _vehicle_position_hash[ (x+y)&0xFFFF ];
while (veh != INVALID_VEHICLE) { while (veh != INVALID_VEHICLE) {
Vehicle *v = &_vehicles[veh]; Vehicle *v = GetVehicle(veh);
void *a; void *a;
if ((a = proc(v, data)) != NULL) if ((a = proc(v, data)) != NULL)
@ -310,7 +318,7 @@ void UpdateVehiclePosHash(Vehicle *v, int x, int y)
if (old_hash != NULL) { if (old_hash != NULL) {
Vehicle *last = NULL; Vehicle *last = NULL;
int idx = *old_hash; int idx = *old_hash;
while((u = &_vehicles[idx]) != v) { while ((u = GetVehicle(idx)) != v) {
idx = u->next_hash; idx = u->next_hash;
assert(idx != INVALID_VEHICLE); assert(idx != INVALID_VEHICLE);
last = u; last = u;
@ -335,7 +343,7 @@ void InitializeVehicles()
int i; int i;
// clear it... // clear it...
memset(&_vehicles, 0, sizeof(_vehicles)); memset(&_vehicles, 0, sizeof(_vehicles[0]) * _vehicles_size);
memset(&_waypoints, 0, sizeof(_waypoints)); memset(&_waypoints, 0, sizeof(_waypoints));
memset(&_depots, 0, sizeof(_depots)); memset(&_depots, 0, sizeof(_depots));
@ -359,24 +367,25 @@ Vehicle *GetPrevVehicleInChain(Vehicle *v)
{ {
Vehicle *org = v; Vehicle *org = v;
v = _vehicles; FOR_ALL_VEHICLES(v) {
while (v->type != VEH_Train || org != v->next) { if (v->type == VEH_Train && org == v->next)
if (++v == endof(_vehicles)) return v;
return NULL;
} }
return v; return NULL;
} }
Vehicle *GetFirstVehicleInChain(Vehicle *v) Vehicle *GetFirstVehicleInChain(Vehicle *v)
{ {
for(;;) { Vehicle *u;
Vehicle *u = v;
v = _vehicles; while (true) {
while (v->type != VEH_Train || u != v->next) { u = v;
if (++v == endof(_vehicles)) v = GetPrevVehicleInChain(v);
return u; /* If there is no such vehicle,
} 'v' == NULL and so 'u' is the first vehicle in chain */
if (v == NULL)
return u;
} }
} }
@ -658,7 +667,7 @@ void ViewportAddVehicles(DrawPixelInfo *dpi)
for(;;) { for(;;) {
veh = _vehicle_position_hash[ (x+y)&0xFFFF ]; veh = _vehicle_position_hash[ (x+y)&0xFFFF ];
while (veh != INVALID_VEHICLE) { while (veh != INVALID_VEHICLE) {
v = &_vehicles[veh]; v = GetVehicle(veh);
if (!(v->vehstatus & VS_HIDDEN) && if (!(v->vehstatus & VS_HIDDEN) &&
dpi->left <= v->right_coord && dpi->left <= v->right_coord &&
@ -1410,7 +1419,7 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
the last 8 bit is the engine. The 8 bits in front of the engine is free so it have room for 16 bit engine entries */ the last 8 bit is the engine. The 8 bits in front of the engine is free so it have room for 16 bit engine entries */
uint16 new_engine_type = (uint16)(p2 & 0xFFFF); uint16 new_engine_type = (uint16)(p2 & 0xFFFF);
uint32 autorefit_money = (p2 >> 16) * 100000; uint32 autorefit_money = (p2 >> 16) * 100000;
Vehicle *v = DEREF_VEHICLE(p1); Vehicle *v = GetVehicle(p1);
int cost, build_cost; int cost, build_cost;
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
@ -1628,7 +1637,7 @@ int32 CmdNameVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
Vehicle *v; Vehicle *v;
StringID str; StringID str;
v = &_vehicles[p1]; v = GetVehicle(p1);
if (!CheckOwnership(v->owner)) if (!CheckOwnership(v->owner))
return CMD_ERROR; return CMD_ERROR;
@ -2013,10 +2022,11 @@ static void Load_VEHS()
Vehicle *v; Vehicle *v;
while ((index = SlIterateArray()) != -1) { while ((index = SlIterateArray()) != -1) {
Vehicle *v = &_vehicles[index]; Vehicle *v = GetVehicle(index);
v->next_in_chain_old = INVALID_VEHICLE; v->next_in_chain_old = INVALID_VEHICLE;
SlObject(v, _veh_descs[SlReadByte()]); SlObject(v, _veh_descs[SlReadByte()]);
v->next = v->next_in_chain_old == INVALID_VEHICLE ? NULL : &_vehicles[v->next_in_chain_old]; v->next = (v->next_in_chain_old == INVALID_VEHICLE) ? NULL : GetVehicle(v->next_in_chain_old);
if (v->type == VEH_Train) if (v->type == VEH_Train)
v->u.rail.first_engine = 0xffff; v->u.rail.first_engine = 0xffff;
@ -2035,6 +2045,11 @@ static void Load_VEHS()
for (w = v->next; w; w = w->next) for (w = v->next; w; w = w->next)
w->u.rail.first_engine = v->engine_type; w->u.rail.first_engine = v->engine_type;
} }
/* This is to ensure all pointers are within the limits of
_vehicles_size */
if (_vehicle_id_ctr_day >= _vehicles_size)
_vehicle_id_ctr_day = 0;
} }
static const byte _depot_desc[] = { static const byte _depot_desc[] = {

View File

@ -408,9 +408,6 @@ byte GetDirectionTowards(Vehicle *v, int x, int y);
#define BEGIN_ENUM_WAGONS(v) do { #define BEGIN_ENUM_WAGONS(v) do {
#define END_ENUM_WAGONS(v) } while ( (v=v->next) != NULL); #define END_ENUM_WAGONS(v) } while ( (v=v->next) != NULL);
#define DEREF_VEHICLE(i) (&_vehicles[i])
#define FOR_ALL_VEHICLES(v) for(v=_vehicles; v != endof(_vehicles); v++)
/* vehicle.c */ /* vehicle.c */
enum { enum {
NUM_NORMAL_VEHICLES = 2048, NUM_NORMAL_VEHICLES = 2048,
@ -419,6 +416,18 @@ enum {
}; };
VARDEF Vehicle _vehicles[NUM_VEHICLES]; VARDEF Vehicle _vehicles[NUM_VEHICLES];
VARDEF uint _vehicles_size;
VARDEF SortStruct *_vehicle_sort;
static inline Vehicle *GetVehicle(uint index)
{
assert(index < _vehicles_size);
return &_vehicles[index];
}
#define FOR_ALL_VEHICLES(v) for(v = _vehicles; v != &_vehicles[_vehicles_size]; v++)
#define FOR_ALL_VEHICLES_FROM(v, from) for(v = GetVehicle(from); v != &_vehicles[_vehicles_size]; v++)
VARDEF Order _order_array[5000]; VARDEF Order _order_array[5000];
VARDEF Order *_ptr_to_next_order; VARDEF Order *_ptr_to_next_order;

View File

@ -80,13 +80,17 @@ void ResortVehicleLists(void)
void BuildVehicleList(vehiclelist_d *vl, int type, int owner, int station) void BuildVehicleList(vehiclelist_d *vl, int type, int owner, int station)
{ {
SortStruct sort_list[NUM_NORMAL_VEHICLES];
int subtype = (type != VEH_Aircraft) ? 0 : 2; int subtype = (type != VEH_Aircraft) ? 0 : 2;
int n = 0; int n = 0;
int i; int i;
if (!(vl->flags & VL_REBUILD)) return; if (!(vl->flags & VL_REBUILD)) return;
/* Create array for sorting */
_vehicle_sort = realloc(_vehicle_sort, _vehicles_size * sizeof(_vehicle_sort[0]));
if (_vehicle_sort == NULL)
error("Could not allocate memory for the vehicle-sorting-list");
DEBUG(misc, 1) ("Building vehicle list for player %d station %d...", DEBUG(misc, 1) ("Building vehicle list for player %d station %d...",
owner, station); owner, station);
@ -97,8 +101,8 @@ void BuildVehicleList(vehiclelist_d *vl, int type, int owner, int station)
const Order *ord; const Order *ord;
for (ord = v->schedule_ptr; ord->type != OT_NOTHING; ++ord) for (ord = v->schedule_ptr; ord->type != OT_NOTHING; ++ord)
if (ord->type == OT_GOTO_STATION && ord->station == station) { if (ord->type == OT_GOTO_STATION && ord->station == station) {
sort_list[n].index = v - _vehicles; _vehicle_sort[n].index = v->index;
sort_list[n].owner = v->owner; _vehicle_sort[n].owner = v->owner;
++n; ++n;
break; break;
} }
@ -108,18 +112,20 @@ void BuildVehicleList(vehiclelist_d *vl, int type, int owner, int station)
const Vehicle *v; const Vehicle *v;
FOR_ALL_VEHICLES(v) { FOR_ALL_VEHICLES(v) {
if (v->type == type && v->subtype <= subtype && v->owner == owner) { if (v->type == type && v->subtype <= subtype && v->owner == owner) {
sort_list[n].index = v - _vehicles; _vehicle_sort[n].index = v->index;
sort_list[n].owner = v->owner; _vehicle_sort[n].owner = v->owner;
++n; ++n;
} }
} }
} }
vl->sort_list = realloc(vl->sort_list, n * sizeof(vl->sort_list[0])); /* XXX unchecked malloc */ vl->sort_list = realloc(vl->sort_list, n * sizeof(vl->sort_list[0]));
if (vl->sort_list == NULL)
error("Could not allocate memory for the vehicle-sorting-list");
vl->list_length = n; vl->list_length = n;
for (i = 0; i < n; ++i) for (i = 0; i < n; ++i)
vl->sort_list[i] = sort_list[i]; vl->sort_list[i] = _vehicle_sort[i];
vl->flags &= ~VL_REBUILD; vl->flags &= ~VL_REBUILD;
vl->flags |= VL_RESORT; vl->flags |= VL_RESORT;
@ -176,7 +182,7 @@ int CDECL GeneralOwnerSorter(const void *a, const void *b)
*/ */
int CDECL VehicleUnsortedSorter(const void *a, const void *b) int CDECL VehicleUnsortedSorter(const void *a, const void *b)
{ {
return DEREF_VEHICLE((*(const SortStruct*)a).index)->index - DEREF_VEHICLE((*(const SortStruct*)b).index)->index; return GetVehicle((*(const SortStruct*)a).index)->index - GetVehicle((*(const SortStruct*)b).index)->index;
} }
// if the sorting criteria had the same value, sort vehicle by unitnumber // if the sorting criteria had the same value, sort vehicle by unitnumber
@ -184,8 +190,8 @@ int CDECL VehicleUnsortedSorter(const void *a, const void *b)
int CDECL VehicleNumberSorter(const void *a, const void *b) int CDECL VehicleNumberSorter(const void *a, const void *b)
{ {
const Vehicle *va = DEREF_VEHICLE((*(const SortStruct*)a).index); const Vehicle *va = GetVehicle((*(const SortStruct*)a).index);
const Vehicle *vb = DEREF_VEHICLE((*(const SortStruct*)b).index); const Vehicle *vb = GetVehicle((*(const SortStruct*)b).index);
int r = va->unitnumber - vb->unitnumber; int r = va->unitnumber - vb->unitnumber;
return (_internal_sort_order & 1) ? -r : r; return (_internal_sort_order & 1) ? -r : r;
@ -196,8 +202,8 @@ int CDECL VehicleNameSorter(const void *a, const void *b)
{ {
const SortStruct *cmp1 = (const SortStruct*)a; const SortStruct *cmp1 = (const SortStruct*)a;
const SortStruct *cmp2 = (const SortStruct*)b; const SortStruct *cmp2 = (const SortStruct*)b;
const Vehicle *va = DEREF_VEHICLE(cmp1->index); const Vehicle *va = GetVehicle(cmp1->index);
const Vehicle *vb = DEREF_VEHICLE(cmp2->index); const Vehicle *vb = GetVehicle(cmp2->index);
char buf1[64] = "\0"; char buf1[64] = "\0";
int r; int r;
@ -224,8 +230,8 @@ int CDECL VehicleNameSorter(const void *a, const void *b)
int CDECL VehicleAgeSorter(const void *a, const void *b) int CDECL VehicleAgeSorter(const void *a, const void *b)
{ {
const Vehicle *va = DEREF_VEHICLE((*(const SortStruct*)a).index); const Vehicle *va = GetVehicle((*(const SortStruct*)a).index);
const Vehicle *vb = DEREF_VEHICLE((*(const SortStruct*)b).index); const Vehicle *vb = GetVehicle((*(const SortStruct*)b).index);
int r = va->age - vb->age; int r = va->age - vb->age;
VEHICLEUNITNUMBERSORTER(r, va, vb); VEHICLEUNITNUMBERSORTER(r, va, vb);
@ -235,8 +241,8 @@ int CDECL VehicleAgeSorter(const void *a, const void *b)
int CDECL VehicleProfitThisYearSorter(const void *a, const void *b) int CDECL VehicleProfitThisYearSorter(const void *a, const void *b)
{ {
const Vehicle *va = DEREF_VEHICLE((*(const SortStruct*)a).index); const Vehicle *va = GetVehicle((*(const SortStruct*)a).index);
const Vehicle *vb = DEREF_VEHICLE((*(const SortStruct*)b).index); const Vehicle *vb = GetVehicle((*(const SortStruct*)b).index);
int r = va->profit_this_year - vb->profit_this_year; int r = va->profit_this_year - vb->profit_this_year;
VEHICLEUNITNUMBERSORTER(r, va, vb); VEHICLEUNITNUMBERSORTER(r, va, vb);
@ -246,8 +252,8 @@ int CDECL VehicleProfitThisYearSorter(const void *a, const void *b)
int CDECL VehicleProfitLastYearSorter(const void *a, const void *b) int CDECL VehicleProfitLastYearSorter(const void *a, const void *b)
{ {
const Vehicle *va = DEREF_VEHICLE((*(const SortStruct*)a).index); const Vehicle *va = GetVehicle((*(const SortStruct*)a).index);
const Vehicle *vb = DEREF_VEHICLE((*(const SortStruct*)b).index); const Vehicle *vb = GetVehicle((*(const SortStruct*)b).index);
int r = va->profit_last_year - vb->profit_last_year; int r = va->profit_last_year - vb->profit_last_year;
VEHICLEUNITNUMBERSORTER(r, va, vb); VEHICLEUNITNUMBERSORTER(r, va, vb);
@ -257,8 +263,8 @@ int CDECL VehicleProfitLastYearSorter(const void *a, const void *b)
int CDECL VehicleCargoSorter(const void *a, const void *b) int CDECL VehicleCargoSorter(const void *a, const void *b)
{ {
const Vehicle *va = DEREF_VEHICLE((*(const SortStruct*)a).index); const Vehicle *va = GetVehicle((*(const SortStruct*)a).index);
const Vehicle *vb = DEREF_VEHICLE((*(const SortStruct*)b).index); const Vehicle *vb = GetVehicle((*(const SortStruct*)b).index);
const Vehicle *v; const Vehicle *v;
int r = 0; int r = 0;
int i; int i;
@ -286,8 +292,8 @@ int CDECL VehicleCargoSorter(const void *a, const void *b)
int CDECL VehicleReliabilitySorter(const void *a, const void *b) int CDECL VehicleReliabilitySorter(const void *a, const void *b)
{ {
const Vehicle *va = DEREF_VEHICLE((*(const SortStruct*)a).index); const Vehicle *va = GetVehicle((*(const SortStruct*)a).index);
const Vehicle *vb = DEREF_VEHICLE((*(const SortStruct*)b).index); const Vehicle *vb = GetVehicle((*(const SortStruct*)b).index);
int r = va->reliability - vb->reliability; int r = va->reliability - vb->reliability;
VEHICLEUNITNUMBERSORTER(r, va, vb); VEHICLEUNITNUMBERSORTER(r, va, vb);
@ -297,8 +303,8 @@ int CDECL VehicleReliabilitySorter(const void *a, const void *b)
int CDECL VehicleMaxSpeedSorter(const void *a, const void *b) int CDECL VehicleMaxSpeedSorter(const void *a, const void *b)
{ {
const Vehicle *va = DEREF_VEHICLE((*(const SortStruct*)a).index); const Vehicle *va = GetVehicle((*(const SortStruct*)a).index);
const Vehicle *vb = DEREF_VEHICLE((*(const SortStruct*)b).index); const Vehicle *vb = GetVehicle((*(const SortStruct*)b).index);
int r = va->max_speed - vb->max_speed; int r = va->max_speed - vb->max_speed;
VEHICLEUNITNUMBERSORTER(r, va, vb); VEHICLEUNITNUMBERSORTER(r, va, vb);

View File

@ -116,7 +116,7 @@ void AssignWindowViewport(Window *w, int x, int y,
if (follow_flags & 0x80000000) { if (follow_flags & 0x80000000) {
Vehicle *veh; Vehicle *veh;
WP(w,vp_d).follow_vehicle = (VehicleID)(follow_flags & 0xFFFF); WP(w,vp_d).follow_vehicle = (VehicleID)(follow_flags & 0xFFFF);
veh = &_vehicles[WP(w,vp_d).follow_vehicle]; veh = GetVehicle(WP(w,vp_d).follow_vehicle);
pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos); pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos);
} else { } else {
int x = GET_TILE_X(follow_flags) * 16; int x = GET_TILE_X(follow_flags) * 16;
@ -1271,7 +1271,7 @@ void UpdateViewportPosition(Window *w)
Vehicle *veh; Vehicle *veh;
Point pt; Point pt;
veh = &_vehicles[WP(w,vp_d).follow_vehicle]; veh = GetVehicle(WP(w,vp_d).follow_vehicle);
pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos); pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos);
SetViewportPosition(w, pt.x, pt.y); SetViewportPosition(w, pt.x, pt.y);
} else { } else {