diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index c9fec08..ff9dafc 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -1672,6 +1672,10 @@ > + + diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index a3c51ea..304962d 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -1669,6 +1669,10 @@ > + + diff --git a/source.list b/source.list index 4837913..8ba5c2b 100644 --- a/source.list +++ b/source.list @@ -343,6 +343,7 @@ video/cocoa/cocoa_v.h core/alloc_func.cpp core/alloc_func.hpp core/alloc_type.hpp +core/autogrowvec_type.hpp core/bitmath_func.cpp core/bitmath_func.hpp core/endian_func.hpp diff --git a/src/ai/api/ai_station.cpp b/src/ai/api/ai_station.cpp index 5e25e5d..1f2e341 100644 --- a/src/ai/api/ai_station.cpp +++ b/src/ai/api/ai_station.cpp @@ -33,18 +33,20 @@ /* static */ int32 AIStation::GetCargoWaiting(StationID station_id, CargoID cargo_id) { - if (!IsValidStation(station_id)) return -1; if (!AICargo::IsValidCargo(cargo_id)) return -1; + const Station *st = ::Station::GetIfValid(station_id); + if (st == NULL) return -1; - return ::Station::Get(station_id)->goods[cargo_id].cargo.Count(); + return st->goods[cargo_id].cargo.Count(); } /* static */ int32 AIStation::GetCargoRating(StationID station_id, CargoID cargo_id) { - if (!IsValidStation(station_id)) return -1; if (!AICargo::IsValidCargo(cargo_id)) return -1; + const Station *st = ::Station::GetIfValid(station_id); + if (st == NULL) return -1; - return ::ToPercent8(::Station::Get(station_id)->goods[cargo_id].rating); + return ::ToPercent8(st->goods[cargo_id].rating); } /* static */ int32 AIStation::GetCoverageRadius(AIStation::StationType station_type) diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 52a0116..9d8ca29 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -1305,9 +1305,9 @@ static void MaybeCrashAirplane(Aircraft *v) if (GB(Random(), 0, 22) > prob) return; /* Crash the airplane. Remove all goods stored at the station. */ - for (CargoID i = 0; i < NUM_CARGO; i++) { - st->goods[i].rating = 1; - st->goods[i].cargo.Truncate(0); + for (Station::GoodsVector::Iterator i(st->goods.Begin()); i != st->goods.End(); ++i) { + i->rating = 1; + i->cargo.Truncate(0); } CrashAirplane(v); diff --git a/src/cargopacket.cpp b/src/cargopacket.cpp index 418eb8e..626dc89 100644 --- a/src/cargopacket.cpp +++ b/src/cargopacket.cpp @@ -31,6 +31,17 @@ CargoPacket::CargoPacket() this->source_id = INVALID_SOURCE; } +bool CargoPacket::operator==(const CargoPacket &other) const +{ + return this->feeder_share == other.feeder_share && + this->count == other.count && + this->days_in_transit == other.days_in_transit && + this->source_id == other.source_id && + this->source == other.source && + this->source_xy == other.source_xy && + this->loaded_at_xy == other.loaded_at_xy; +} + /* NOTE: We have to zero memory ourselves here because we are using a 'new' * that, in contrary to all other pools, does not memset to 0. */ CargoPacket::CargoPacket(StationID source, TileIndex source_xy, uint16 count, SourceType source_type, SourceID source_id) : @@ -99,6 +110,46 @@ CargoList::~CargoList() } template +CargoList::CargoList(const CargoList &other) : + count(other.count), + cargo_days_in_transit(other.cargo_days_in_transit) +{ + for(ConstIterator i(other.packets.begin()); i != other.packets.end(); ++i) { + this->packets.push_back(new CargoPacket(**i)); + } +} + +template +CargoList &CargoList::operator=(const CargoList &other) +{ + if (this != &other) { + this->count = other.count; + this->cargo_days_in_transit = other.cargo_days_in_transit; + for(ConstIterator i(other.packets.begin()); i != other.packets.end(); ++i) { + this->packets.push_back(new CargoPacket(**i)); + } + } + return *this; +} + +template +bool CargoList::operator==(const CargoList &other) const +{ + if (this->count != other.count || + this->cargo_days_in_transit != other.cargo_days_in_transit || + this->packets.size() != other.packets.size()) { + return false; + } + + ConstIterator i(this->packets.begin()); + ConstIterator j(other.packets.begin()); + for(; i != this->packets.end(); ++i, ++j) { + if (!(**i == **j)) return false; + } + return true; +} + +template void CargoList::RemoveFromCache(const CargoPacket *cp) { this->count -= cp->count; diff --git a/src/cargopacket.h b/src/cargopacket.h index dfd5e72..708b8a1 100644 --- a/src/cargopacket.h +++ b/src/cargopacket.h @@ -85,6 +85,8 @@ public: */ CargoPacket(uint16 count, byte days_in_transit, StationID source, TileIndex source_xy, TileIndex loaded_at_xy, Money feeder_share = 0, SourceType source_type = ST_INDUSTRY, SourceID source_id = INVALID_SOURCE); + bool operator==(const CargoPacket &other) const; + /** Destroy the packet */ ~CargoPacket() { } @@ -227,9 +229,15 @@ protected: public: /** Create the cargo list */ - CargoList() {} + CargoList() : count(0), cargo_days_in_transit(0) {} /** And destroy it ("frees" all cargo packets) */ ~CargoList(); + /** Do a deep copy */ + CargoList(const CargoList &other); + /** Deep copy assignment */ + CargoList &operator=(const CargoList &other); + /** Deep comparison */ + bool operator==(const CargoList &other) const; /** * Returns a pointer to the cargo packet list (so you can iterate over it etc). @@ -351,6 +359,14 @@ public: /** The vehicles have a cargo list (and we want that saved). */ friend const struct SaveLoad *GetVehicleDescription(VehicleType vt); + VehicleCargoList() : feeder_share(0) {} + + bool operator==(const VehicleCargoList &other) const + { + return this->feeder_share == other.feeder_share && + this->CargoList::operator==(other); + } + /** * Returns total sum of the feeder share for all packets * @return the before mentioned number diff --git a/src/core/autogrowvec_type.hpp b/src/core/autogrowvec_type.hpp new file mode 100644 index 0000000..369a9dd --- /dev/null +++ b/src/core/autogrowvec_type.hpp @@ -0,0 +1,128 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file autogrowvec_type.hpp Simple vector class that automatically grows when accessed beyond end. */ + + +#ifndef AUTOGROWVECTOR_TYPE_HPP_ +#define AUTOGROWVECTOR_TYPE_HPP_ + +#include "../stdafx.h" +#include "../debug.h" +#include + +template +class AutoGrowVector { +protected: + typedef typename std::vector BaseVector; + BaseVector base; + static const Tvalue empty; + +public: + typedef typename BaseVector::iterator Iterator; + typedef typename BaseVector::const_iterator ConstIterator; + + /** + * Get the number of items in the list. + */ + FORCEINLINE uint Length() const + { + return this->base.size(); + } + + /** + * Get the pointer to the first item (const) + * + * @return the pointer to the first item + */ + FORCEINLINE ConstIterator Begin() const + { + return this->base.begin(); + } + + /** + * Get the pointer to the first item + * + * @return the pointer to the first item + */ + FORCEINLINE Iterator Begin() + { + return this->base.begin(); + } + + /** + * Get the pointer behind the last valid item (const) + * + * @return the pointer behind the last valid item + */ + FORCEINLINE ConstIterator End() const + { + return this->base.end(); + } + + /** + * Get the pointer behind the last valid item + * + * @return the pointer behind the last valid item + */ + FORCEINLINE Iterator End() + { + return this->base.end(); + } + + /** + * Get item "number"; resize the vector and create new item if necessary + * + * @param index the positon of the item + * @return the item + */ + FORCEINLINE Tvalue &operator[](uint index) + { + if (index >= this->base.size()) { + this->base.resize(index + 1, AutoGrowVector::empty); + } + return this->base[index]; + } + + /** + * Get item "number" (const) or empty item if the index is unused + * + * @param index the positon of the item + * @return the item + */ + FORCEINLINE const Tvalue &operator[](uint index) const + { + if (index < this->base.size()) { + return this->base[index]; + } else { + return AutoGrowVector::empty; + } + } + + FORCEINLINE void Reserve(uint new_size) + { + this->base.reserve(new_size); + } + + void Compact() + { + while(!this->base.empty()) { + if (this->base.back() == AutoGrowVector::empty) { + this->base.pop_back(); + } else { + return; + } + } + } +}; + +template const Tvalue AutoGrowVector::empty = Tvalue(); + + +#endif /* AUTOGROWVECTOR_TYPE_HPP_ */ diff --git a/src/core/pool_type.hpp b/src/core/pool_type.hpp index 9c32a81..f267c12 100644 --- a/src/core/pool_type.hpp +++ b/src/core/pool_type.hpp @@ -83,6 +83,24 @@ struct Pool { Tindex index; ///< Index of this pool item /** + * Don't initialize the index on construction - it's done by operator new. + */ + FORCEINLINE PoolItem() {} + + /** + * Don't copy the index on copy-constructing. + */ + FORCEINLINE PoolItem(const PoolItem &other) {} + + /** + * Don't copy the index on assignment. + */ + FORCEINLINE PoolItem &operator=(const PoolItem &other) + { + return *this; + } + + /** * Allocates space for new Titem * @param size size of Titem * @return pointer to allocated memory diff --git a/src/economy.cpp b/src/economy.cpp index de56391..0e37ce5 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -1414,7 +1414,11 @@ void LoadUnloadStation(Station *st) int cargo_left[NUM_CARGO]; - for (uint i = 0; i < NUM_CARGO; i++) cargo_left[i] = st->goods[i].cargo.Count(); + Station::GoodsVector::ConstIterator begin(st->goods.Begin()); + CargoID length(st->goods.Length()); + for (CargoID i = 0; i < length; ++i) { + cargo_left[i] = (begin + i)->cargo.Count(); + } std::list::iterator iter; for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) { diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index 8dafa62..d3b3a48 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -517,8 +517,10 @@ uint32 Station::GetNewGRFVariable(const ResolverObject *object, byte variable, b CargoID cargo_type; uint32 value = 0; - for (cargo_type = 0; cargo_type < NUM_CARGO; cargo_type++) { - if (HasBit(this->goods[cargo_type].acceptance_pickup, GoodsEntry::PICKUP)) SetBit(value, cargo_type); + GoodsVector::ConstIterator begin(this->goods.Begin()); + CargoID length(this->goods.Length()); + for (cargo_type = 0; cargo_type < length; ++cargo_type) { + if (HasBit((begin + cargo_type)->acceptance_pickup, GoodsEntry::PICKUP)) SetBit(value, cargo_type); } return value; } @@ -624,10 +626,14 @@ static const SpriteGroup *StationResolveReal(const ResolverObject *object, const break; case CT_DEFAULT: - for (cargo_type = 0; cargo_type < NUM_CARGO; cargo_type++) { - cargo += st->goods[cargo_type].cargo.Count(); + { + Station::GoodsVector::ConstIterator begin(st->goods.Begin()); + CargoID length(st->goods.Length()); + for (cargo_type = 0; cargo_type < length; cargo_type++) { + cargo += (begin + cargo_type)->cargo.Count(); } break; + } default: cargo = st->goods[cargo_type].cargo.Count(); diff --git a/src/openttd.cpp b/src/openttd.cpp index eb77989..818cc81 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -1165,7 +1165,7 @@ static void CheckCaches() Station *st; FOR_ALL_STATIONS(st) { - for (CargoID c = 0; c < NUM_CARGO; c++) { + for (CargoID c = 0; c < st->goods.Length(); c++) { byte buff[sizeof(StationCargoList)]; memcpy(buff, &st->goods[c].cargo, sizeof(StationCargoList)); st->goods[c].cargo.InvalidateCache(); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 15777af..879d3e2 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1439,9 +1439,9 @@ bool AfterLoadGame() if (CheckSavegameVersion(74)) { Station *st; FOR_ALL_STATIONS(st) { - for (CargoID c = 0; c < NUM_CARGO; c++) { - st->goods[c].last_speed = 0; - if (st->goods[c].cargo.Count() != 0) SetBit(st->goods[c].acceptance_pickup, GoodsEntry::PICKUP); + for (Station::GoodsVector::Iterator i(st->goods.Begin()); i != st->goods.End(); ++i) { + i->last_speed = 0; + if (i->cargo.Count() != 0) SetBit(i->acceptance_pickup, GoodsEntry::PICKUP); } } } diff --git a/src/saveload/cargopacket_sl.cpp b/src/saveload/cargopacket_sl.cpp index 8090ed6..3059aca 100644 --- a/src/saveload/cargopacket_sl.cpp +++ b/src/saveload/cargopacket_sl.cpp @@ -39,10 +39,10 @@ * station where the goods came from is already removed, the source * information is lost. In that case we set it to the position of this * station */ - Station *st; + const Station *st; FOR_ALL_STATIONS(st) { - for (CargoID c = 0; c < NUM_CARGO; c++) { - GoodsEntry *ge = &st->goods[c]; + for (Station::GoodsVector::ConstIterator goods_it(st->goods.Begin()); goods_it != st->goods.End(); ++goods_it) { + const GoodsEntry *ge = &(*goods_it); const StationCargoList::List *packets = ge->cargo.Packets(); for (StationCargoList::ConstIterator it(packets->begin()); it != packets->end(); it++) { @@ -71,7 +71,9 @@ Station *st; FOR_ALL_STATIONS(st) { - for (CargoID c = 0; c < NUM_CARGO; c++) st->goods[c].cargo.InvalidateCache(); + for (Station::GoodsVector::Iterator c(st->goods.Begin()); c != st->goods.End(); ++c) { + c->cargo.InvalidateCache(); + } } } } diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 0e8fea7..4cb1e17 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -46,7 +46,7 @@ #include "saveload_internal.h" -extern const uint16 SAVEGAME_VERSION = 140; +extern const uint16 SAVEGAME_VERSION = SL_VECTOR; SavegameType _savegame_type; ///< type of savegame we are loading diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 0914a50..d83e577 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -79,8 +79,6 @@ enum SLRefType { REF_ORDERLIST = 8, }; -#define SL_MAX_VERSION 255 - enum { INC_VEHICLE_COMMON = 0, }; @@ -338,4 +336,14 @@ bool SaveloadCrashWithMissingNewGRFs(); extern char _savegame_format[8]; +/** + * save/load versions used for the various branches + * SL_TRUNK is always the current trunk version. + */ +enum SaveLoadVersions { + SL_TRUNK = 140, + SL_VECTOR = SL_TRUNK + 5, + SL_MAX_VERSION = 255 +}; + #endif /* SAVELOAD_H */ diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index c705e2b..92ff659 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -102,6 +102,7 @@ void AfterLoadStations() Station *sta = Station::From(st); for (const RoadStop *rs = sta->bus_stops; rs != NULL; rs = rs->next) sta->bus_station.Add(rs->xy); for (const RoadStop *rs = sta->truck_stops; rs != NULL; rs = rs->next) sta->truck_station.Add(rs->xy); + if (CheckSavegameVersion(SL_VECTOR)) sta->goods.Compact(); } StationUpdateAnimTriggers(st); @@ -258,6 +259,12 @@ static void Load_STNS() _waiting_acceptance = 0; uint num_cargo = CheckSavegameVersion(55) ? 12 : NUM_CARGO; + + /* We cannot copy-construct cargo lists here, so we have to make sure they stay in place. + * Also reserving all the intended amount at once is cheaper than constantly re-reserving. + */ + st->goods.Reserve(num_cargo); + for (CargoID i = 0; i < num_cargo; i++) { GoodsEntry *ge = &st->goods[i]; SlObject(ge, GetGoodsDesc()); @@ -292,9 +299,8 @@ static void Ptrs_STNS() Station *st; FOR_ALL_STATIONS(st) { if (!CheckSavegameVersion(68)) { - for (CargoID i = 0; i < NUM_CARGO; i++) { - GoodsEntry *ge = &st->goods[i]; - SlObject(ge, GetGoodsDesc()); + for (Station::GoodsVector::Iterator i = st->goods.Begin(); i != st->goods.End(); ++i) { + SlObject(&(*i), GetGoodsDesc()); } } SlObject(st, _old_station_desc); @@ -320,6 +326,9 @@ static const SaveLoad _base_station_desc[] = { SLE_END() }; +/** the number of goods entries present in a station */ +uint8 _num_goods; + static const SaveLoad _station_desc[] = { SLE_WRITEBYTE(Station, facilities, FACIL_NONE), SLE_ST_INCLUDE(), @@ -345,6 +354,7 @@ static const SaveLoad _station_desc[] = { SLE_VAR(Station, had_vehicle_of_type, SLE_UINT8), SLE_LST(Station, loading_vehicles, REF_VEHICLE), SLE_CONDVAR(Station, always_accepted, SLE_UINT32, 127, SL_MAX_VERSION), + SLEG_CONDVAR(_num_goods, SLE_UINT8, SL_VECTOR, SL_MAX_VERSION), SLE_END() }; @@ -374,12 +384,14 @@ const SaveLoad *GetBaseStationDescription() static void RealSave_STNN(BaseStation *bst) { bool waypoint = (bst->facilities & FACIL_WAYPOINT) != 0; - SlObject(bst, waypoint ? _waypoint_desc : _station_desc); - - if (!waypoint) { + if (waypoint) { + SlObject(bst, _waypoint_desc); + } else { Station *st = Station::From(bst); - for (CargoID i = 0; i < NUM_CARGO; i++) { - SlObject(&st->goods[i], GetGoodsDesc()); + _num_goods = st->goods.Length(); + SlObject(bst, _station_desc); + for (Station::GoodsVector::Iterator it(st->goods.Begin()); it != st->goods.End(); ++it) { + SlObject(&(*it), GetGoodsDesc()); } } @@ -410,7 +422,14 @@ static void Load_STNN() if (!waypoint) { Station *st = Station::From(bst); - for (CargoID i = 0; i < NUM_CARGO; i++) { + uint num_cargo = CheckSavegameVersion(SL_VECTOR) ? (uint)NUM_CARGO : _num_goods; + + /* We cannot copy-construct cargo lists here, so we have to make sure they stay in place. + * Also reserving all the intended amount at once is cheaper than constantly re-reserving. + */ + st->goods.Reserve(num_cargo); + + for (CargoID i = 0; i < num_cargo; i++) { SlObject(&st->goods[i], GetGoodsDesc()); } } @@ -432,9 +451,8 @@ static void Ptrs_STNN() Station *st; FOR_ALL_STATIONS(st) { - for (CargoID i = 0; i < NUM_CARGO; i++) { - GoodsEntry *ge = &st->goods[i]; - SlObject(ge, GetGoodsDesc()); + for (Station::GoodsVector::Iterator it(st->goods.Begin()); it != st->goods.End(); ++it) { + SlObject(&(*it), GetGoodsDesc()); } SlObject(st, _station_desc); } diff --git a/src/station.cpp b/src/station.cpp index 320d641..72d5634 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -94,8 +94,8 @@ Station::~Station() /* Remove all news items */ DeleteStationNews(this->index); - for (CargoID c = 0; c < NUM_CARGO; c++) { - this->goods[c].cargo.Truncate(0); + for (GoodsVector::Iterator i = this->goods.Begin(); i != this->goods.End(); ++i) { + i->cargo.Truncate(0); } CargoPacket::InvalidateAllFrom(this->index); diff --git a/src/station_base.h b/src/station_base.h index e3aa8b7..40c79bd 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -17,6 +17,7 @@ #include "newgrf_airport.h" #include "cargopacket.h" #include "industry_type.h" +#include "core/autogrowvec_type.hpp" typedef Pool StationPool; extern StationPool _station_pool; @@ -37,6 +38,15 @@ struct GoodsEntry { last_age(255) {} + bool operator==(const GoodsEntry &other) const + { + return this->acceptance_pickup == other.acceptance_pickup && + this->days_since_pickup == other.days_since_pickup && + this->last_speed == other.last_speed && + this->last_age == other.last_age && + this->cargo == other.cargo; + } + byte acceptance_pickup; byte days_since_pickup; byte rating; @@ -51,6 +61,8 @@ typedef SmallVector IndustryVector; /** Station data structure */ struct Station : SpecializedStation { public: + typedef AutoGrowVector GoodsVector; + RoadStop *GetPrimaryRoadStop(RoadStopType type) const { return type == ROADSTOP_BUS ? bus_stops : truck_stops; @@ -90,7 +102,7 @@ public: byte last_vehicle_type; std::list loading_vehicles; - GoodsEntry goods[NUM_CARGO]; ///< Goods at this station + GoodsVector goods; ///< Goods at this station uint32 always_accepted; ///< Bitmask of always accepted cargo types (by houses, HQs, industry tiles when industry doesn't accept cargo) IndustryVector industries_near; ///< Cached list of industries near the station that can accept cargo, @see DeliverGoodsToIndustry() diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 956079d..09af77d 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -440,8 +440,9 @@ static uint GetAcceptanceMask(const Station *st) { uint mask = 0; - for (CargoID i = 0; i < NUM_CARGO; i++) { - if (HasBit(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE)) mask |= 1 << i; + Station::GoodsVector::ConstIterator begin(st->goods.Begin()); + for (Station::GoodsVector::ConstIterator i(begin); i != st->goods.End(); ++i) { + if (HasBit(i->acceptance_pickup, GoodsEntry::ACCEPTANCE)) mask |= 1 << (i - begin); } return mask; } @@ -581,7 +582,10 @@ void UpdateStationAcceptance(Station *st, bool show_msg) amt = 0; } - SB(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, amt >= 8); + /* non-existing goods entry means good isn't accepted */ + if (amt >= 8 || i < st->goods.Length()) { + SB(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, amt >= 8); + } } /* Only show a message in case the acceptance was actually changed. */ @@ -3011,6 +3015,8 @@ static void UpdateStationRating(Station *st) const CargoSpec *cs; FOR_ALL_CARGOSPECS(cs) { + /* no need to update ratings which are not there */ + if (st->goods.Length() <= cs->Index()) break; GoodsEntry *ge = &st->goods[cs->Index()]; /* Slowly increase the rating back to his original level in the case we * didn't deliver cargo yet to this station. This happens when a bribe @@ -3174,8 +3180,8 @@ void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint rad FOR_ALL_STATIONS(st) { if (st->owner == owner && DistanceManhattan(tile, st->xy) <= radius) { - for (CargoID i = 0; i < NUM_CARGO; i++) { - GoodsEntry *ge = &st->goods[i]; + for (Station::GoodsVector::Iterator i = st->goods.Begin(); i != st->goods.End(); ++i) { + GoodsEntry *ge = &(*i); if (ge->acceptance_pickup != 0) { ge->rating = Clamp(ge->rating + amount, 0, 255); @@ -3384,14 +3390,6 @@ void BuildOilRig(TileIndex tile) st->rect.BeforeAddTile(tile, StationRect::ADD_FORCE); - for (CargoID j = 0; j < NUM_CARGO; j++) { - st->goods[j].acceptance_pickup = 0; - st->goods[j].days_since_pickup = 255; - st->goods[j].rating = INITIAL_STATION_RATING; - st->goods[j].last_speed = 0; - st->goods[j].last_age = 255; - } - st->UpdateVirtCoord(); UpdateStationAcceptance(st, false); st->RecomputeIndustriesNear(); diff --git a/src/station_gui.cpp b/src/station_gui.cpp index e731931..892145d 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -236,7 +236,7 @@ protected: if (st->owner == owner || (st->owner == OWNER_NONE && HasStationInUse(st->index, owner))) { if (this->facilities & st->facilities) { // only stations with selected facilities int num_waiting_cargo = 0; - for (CargoID j = 0; j < NUM_CARGO; j++) { + for (CargoID j = 0; j < st->goods.Length(); j++) { if (!st->goods[j].cargo.Empty()) { num_waiting_cargo++; // count number of waiting cargo if (HasBit(this->cargo_filter, j)) { @@ -288,7 +288,7 @@ protected: { Money diff = 0; - for (CargoID j = 0; j < NUM_CARGO; j++) { + for (CargoID j = 0; j < max((*a)->goods.Length(), (*b)->goods.Length()); j++) { if (!HasBit(cargo_filter, j)) continue; if (!(*a)->goods[j].cargo.Empty()) diff += GetTransportedGoodsIncome((*a)->goods[j].cargo.Count(), 20, 50, j); if (!(*b)->goods[j].cargo.Empty()) diff -= GetTransportedGoodsIncome((*b)->goods[j].cargo.Count(), 20, 50, j); @@ -303,7 +303,7 @@ protected: byte maxr1 = 0; byte maxr2 = 0; - for (CargoID j = 0; j < NUM_CARGO; j++) { + for (CargoID j = 0; j < max((*a)->goods.Length(), (*b)->goods.Length()); j++) { if (!HasBit(cargo_filter, j)) continue; if (HasBit((*a)->goods[j].acceptance_pickup, GoodsEntry::PICKUP)) maxr1 = max(maxr1, (*a)->goods[j].rating); if (HasBit((*b)->goods[j].acceptance_pickup, GoodsEntry::PICKUP)) maxr2 = max(maxr2, (*b)->goods[j].rating); @@ -318,7 +318,7 @@ protected: byte minr1 = 255; byte minr2 = 255; - for (CargoID j = 0; j < NUM_CARGO; j++) { + for (CargoID j = 0; j < max((*a)->goods.Length(), (*b)->goods.Length()); j++) { if (!HasBit(cargo_filter, j)) continue; if (HasBit((*a)->goods[j].acceptance_pickup, GoodsEntry::PICKUP)) minr1 = min(minr1, (*a)->goods[j].rating); if (HasBit((*b)->goods[j].acceptance_pickup, GoodsEntry::PICKUP)) minr2 = min(minr2, (*b)->goods[j].rating); @@ -466,7 +466,7 @@ public: x += rtl ? -5 : 5; /* show cargo waiting and station ratings */ - for (CargoID j = 0; j < NUM_CARGO; j++) { + for (CargoID j = 0; j < st->goods.Length(); j++) { if (!st->goods[j].cargo.Empty()) { /* For RTL we work in exactly the opposite direction. So * decrement the space needed first, then draw to the left @@ -1001,7 +1001,7 @@ struct StationViewWindow : public Window { const Station *st = Station::Get(station_id); /* count types of cargos waiting in station */ - for (CargoID i = 0; i < NUM_CARGO; i++) { + for (CargoID i = 0; i < st->goods.Length(); i++) { if (st->goods[i].cargo.Empty()) { this->cargo_rows[i] = 0; } else { @@ -1054,7 +1054,7 @@ struct StationViewWindow : public Window { const Station *st = Station::Get(this->window_number); if (--pos < 0) { StringID str = STR_JUST_NOTHING; - for (CargoID i = 0; i < NUM_CARGO; i++) { + for (CargoID i = 0; i < st->goods.Length(); i++) { if (!st->goods[i].cargo.Empty()) str = STR_EMPTY; } SetDParam(0, str); @@ -1107,7 +1107,7 @@ struct StationViewWindow : public Window { const Station *st = Station::Get(this->window_number); uint32 cargo_mask = 0; - for (CargoID i = 0; i < NUM_CARGO; i++) { + for (CargoID i = 0; i < st->goods.Length(); i++) { if (HasBit(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE)) SetBit(cargo_mask, i); } Rect s = {r.left + WD_FRAMERECT_LEFT, r.top + WD_FRAMERECT_TOP, r.right - WD_FRAMERECT_RIGHT, INT32_MAX}; diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 2a4e367..201d588 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -2447,7 +2447,9 @@ static void TownActionBribe(Town *t) Station *st; FOR_ALL_STATIONS(st) { if (st->town == t && st->owner == _current_company) { - for (CargoID i = 0; i < NUM_CARGO; i++) st->goods[i].rating = 0; + for (Station::GoodsVector::Iterator i = st->goods.Begin(); i != st->goods.End(); ++i) { + i->rating = 0; + } } }