mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r20857) -Fix [FS#3637]: The station with the second highest rating was doubly penalised when distributing cargo. Now the penalty is completely removed and the granularity/precision of the distribution in increased by using fractional cargo. This should make competing stations less "all-or-nothing".
This commit is contained in:
parent
897bb71621
commit
b4f6201e94
|
@ -212,8 +212,9 @@
|
||||||
* 147 20621
|
* 147 20621
|
||||||
* 148 20659
|
* 148 20659
|
||||||
* 149 20832
|
* 149 20832
|
||||||
|
* 150 20857
|
||||||
*/
|
*/
|
||||||
extern const uint16 SAVEGAME_VERSION = 149; ///< current savegame version of OpenTTD
|
extern const uint16 SAVEGAME_VERSION = 150; ///< current savegame version of OpenTTD
|
||||||
|
|
||||||
SavegameType _savegame_type; ///< type of savegame we are loading
|
SavegameType _savegame_type; ///< type of savegame we are loading
|
||||||
|
|
||||||
|
|
|
@ -238,6 +238,7 @@ const SaveLoad *GetGoodsDesc()
|
||||||
SLE_VAR(GoodsEntry, last_age, SLE_UINT8),
|
SLE_VAR(GoodsEntry, last_age, SLE_UINT8),
|
||||||
SLEG_CONDVAR( _cargo_feeder_share, SLE_FILE_U32 | SLE_VAR_I64, 14, 64),
|
SLEG_CONDVAR( _cargo_feeder_share, SLE_FILE_U32 | SLE_VAR_I64, 14, 64),
|
||||||
SLEG_CONDVAR( _cargo_feeder_share, SLE_INT64, 65, 67),
|
SLEG_CONDVAR( _cargo_feeder_share, SLE_INT64, 65, 67),
|
||||||
|
SLE_CONDVAR(GoodsEntry, amount_fract, SLE_UINT8, 150, SL_MAX_VERSION),
|
||||||
SLE_CONDLST(GoodsEntry, cargo.packets, REF_CARGO_PACKET, 68, SL_MAX_VERSION),
|
SLE_CONDLST(GoodsEntry, cargo.packets, REF_CARGO_PACKET, 68, SL_MAX_VERSION),
|
||||||
|
|
||||||
SLE_END()
|
SLE_END()
|
||||||
|
|
|
@ -42,6 +42,7 @@ struct GoodsEntry {
|
||||||
byte rating;
|
byte rating;
|
||||||
byte last_speed;
|
byte last_speed;
|
||||||
byte last_age;
|
byte last_age;
|
||||||
|
byte amount_fract; ///< Fractional part of the amount in the cargo list
|
||||||
StationCargoList cargo; ///< The cargo packets of cargo waiting in this station
|
StationCargoList cargo; ///< The cargo packets of cargo waiting in this station
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3188,8 +3188,15 @@ void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint rad
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceType source_type, SourceID source_id)
|
static uint UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceType source_type, SourceID source_id)
|
||||||
{
|
{
|
||||||
|
amount += st->goods[type].amount_fract;
|
||||||
|
st->goods[type].amount_fract = GB(amount, 0, 8);
|
||||||
|
|
||||||
|
amount >>= 8;
|
||||||
|
/* No new "real" cargo item yet. */
|
||||||
|
if (amount == 0) return 0;
|
||||||
|
|
||||||
st->goods[type].cargo.Append(new CargoPacket(st->index, st->xy, amount, source_type, source_id));
|
st->goods[type].cargo.Append(new CargoPacket(st->index, st->xy, amount, source_type, source_id));
|
||||||
SetBit(st->goods[type].acceptance_pickup, GoodsEntry::PICKUP);
|
SetBit(st->goods[type].acceptance_pickup, GoodsEntry::PICKUP);
|
||||||
|
|
||||||
|
@ -3198,6 +3205,7 @@ static void UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceT
|
||||||
|
|
||||||
SetWindowDirty(WC_STATION_VIEW, st->index);
|
SetWindowDirty(WC_STATION_VIEW, st->index);
|
||||||
st->MarkTilesDirty(true);
|
st->MarkTilesDirty(true);
|
||||||
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsUniqueStationName(const char *name)
|
static bool IsUniqueStationName(const char *name)
|
||||||
|
@ -3328,11 +3336,13 @@ uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, Sourc
|
||||||
/* no stations around at all? */
|
/* no stations around at all? */
|
||||||
if (st1 == NULL) return 0;
|
if (st1 == NULL) return 0;
|
||||||
|
|
||||||
|
/* From now we'll calculate with fractal cargo amounts.
|
||||||
|
* First determine how much cargo we really have. */
|
||||||
|
amount *= best_rating1 + 1;
|
||||||
|
|
||||||
if (st2 == NULL) {
|
if (st2 == NULL) {
|
||||||
/* only one station around */
|
/* only one station around */
|
||||||
uint moved = amount * best_rating1 / 256 + 1;
|
return UpdateStationWaiting(st1, type, amount, source_type, source_id);
|
||||||
UpdateStationWaiting(st1, type, moved, source_type, source_id);
|
|
||||||
return moved;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* several stations around, the best two (highest rating) are in st1 and st2 */
|
/* several stations around, the best two (highest rating) are in st1 and st2 */
|
||||||
|
@ -3340,26 +3350,19 @@ uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, Sourc
|
||||||
assert(st2 != NULL);
|
assert(st2 != NULL);
|
||||||
assert(best_rating1 != 0 || best_rating2 != 0);
|
assert(best_rating1 != 0 || best_rating2 != 0);
|
||||||
|
|
||||||
/* the 2nd highest one gets a penalty */
|
/* Then determine the amount the worst station gets. We do it this way as the
|
||||||
best_rating2 >>= 1;
|
* best should get a bonus, which in this case is the rounding difference from
|
||||||
|
* this calculation. In reality that will mean the bonus will be pretty low.
|
||||||
|
* Nevertheless, the best station should always get the most cargo regardless
|
||||||
|
* of rounding issues. */
|
||||||
|
uint worst_cargo = amount * best_rating2 / (best_rating1 + best_rating2);
|
||||||
|
assert(worst_cargo <= (amount - worst_cargo));
|
||||||
|
|
||||||
/* amount given to station 1 */
|
/* And then send the cargo to the stations! */
|
||||||
uint t = (best_rating1 * (amount + 1)) / (best_rating1 + best_rating2);
|
uint moved = UpdateStationWaiting(st1, type, amount - worst_cargo, source_type, source_id);
|
||||||
|
/* These two UpdateStationWaiting's can't be in the statement as then the order
|
||||||
uint moved = 0;
|
* of execution would be undefined and that could cause desyncs with callbacks. */
|
||||||
if (t != 0) {
|
return moved + UpdateStationWaiting(st2, type, worst_cargo, source_type, source_id);
|
||||||
moved = t * best_rating1 / 256 + 1;
|
|
||||||
amount -= t;
|
|
||||||
UpdateStationWaiting(st1, type, moved, source_type, source_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amount != 0) {
|
|
||||||
amount = amount * best_rating2 / 256 + 1;
|
|
||||||
moved += amount;
|
|
||||||
UpdateStationWaiting(st2, type, amount, source_type, source_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return moved;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildOilRig(TileIndex tile)
|
void BuildOilRig(TileIndex tile)
|
||||||
|
|
Loading…
Reference in New Issue