--- a/src/economy.cpp Wed Jun 13 11:17:30 2007 +0000
+++ b/src/economy.cpp Wed Jun 13 11:45:14 2007 +0000
@@ -38,6 +38,7 @@
#include "date.h"
#include "cargotype.h"
#include "player_face.h"
+#include "group.h"
/* Score info */
const ScoreInfo _score_info[] = {
@@ -359,12 +360,14 @@
DeleteVehicle(v);
} else {
v->owner = new_player;
+ v->group_id = DEFAULT_GROUP;
if (IsEngineCountable(v)) GetPlayer(new_player)->num_engines[v->engine_type]++;
switch (v->type) {
case VEH_TRAIN: if (IsFrontEngine(v)) v->unitnumber = ++num_train; break;
case VEH_ROAD: v->unitnumber = ++num_road; break;
case VEH_SHIP: v->unitnumber = ++num_ship; break;
case VEH_AIRCRAFT: if (IsNormalAircraft(v)) v->unitnumber = ++num_aircraft; break;
+ default: NOT_REACHED();
}
}
}
@@ -804,6 +807,7 @@
static void FindSubsidyCargoRoute(FoundRoute *fr)
{
Industry *i;
+ const IndustrySpec *ind;
int trans, total;
CargoID cargo;
@@ -811,14 +815,15 @@
fr->from = i = GetRandomIndustry();
if (i == NULL) return;
+ ind = GetIndustrySpec(i->type);
/* Randomize cargo type */
- if (Random()&1 && i->produced_cargo[1] != CT_INVALID) {
- cargo = i->produced_cargo[1];
+ if (HASBIT(Random(), 0) && ind->produced_cargo[1] != CT_INVALID) {
+ cargo = ind->produced_cargo[1];
trans = i->pct_transported[1];
total = i->total_production[1];
} else {
- cargo = i->produced_cargo[0];
+ cargo = ind->produced_cargo[0];
trans = i->pct_transported[0];
total = i->total_production[0];
}
@@ -845,13 +850,19 @@
} else {
/* The destination is an industry */
Industry *i2 = GetRandomIndustry();
+ if (i2 == NULL) {
+ return;
+ }
+
+ ind = GetIndustrySpec(i2->type);
/* The industry must accept the cargo */
- if (i == i2 || i == NULL ||
- (cargo != i2->accepts_cargo[0] &&
- cargo != i2->accepts_cargo[1] &&
- cargo != i2->accepts_cargo[2]))
+ if (i == i2 ||
+ (cargo != ind->accepts_cargo[0] &&
+ cargo != ind->accepts_cargo[1] &&
+ cargo != ind->accepts_cargo[2])) {
return;
+ }
fr->distance = DistanceManhattan(i->xy, i2->xy);
fr->to = i2;
}
@@ -1025,34 +1036,48 @@
static void DeliverGoodsToIndustry(TileIndex xy, CargoID cargo_type, int num_pieces)
{
- Industry* best = NULL;
- Industry* ind;
- uint u;
+ Industry *best = NULL;
+ Industry *ind;
+ const IndustrySpec *indspec;
+ uint best_dist;
+ uint accepted_cargo_index = 0; ///< unlikely value, just for warning removing
/* Check if there's an industry close to the station that accepts the cargo
* XXX - Think of something better to
* 1) Only deliver to industries which are withing the catchment radius
* 2) Distribute between industries if more then one is present */
- u = (_patches.station_spread + 8) * 2;
+ best_dist = (_patches.station_spread + 8) * 2;
FOR_ALL_INDUSTRIES(ind) {
- uint t;
+ indspec = GetIndustrySpec(ind->type);
+ uint i;
- if (( cargo_type == ind->accepts_cargo[0] ||
- cargo_type == ind->accepts_cargo[1] ||
- cargo_type == ind->accepts_cargo[2]
- ) &&
- ind->produced_cargo[0] != CT_INVALID &&
- ind->produced_cargo[0] != cargo_type &&
- (t = DistanceManhattan(ind->xy, xy)) < u) {
- u = t;
+ if (indspec->produced_cargo[0] == CT_INVALID) continue;
+
+ for (i = 0; i < lengthof(indspec->accepts_cargo); i++) {
+ if (cargo_type == indspec->accepts_cargo[i] &&
+ (indspec->input_cargo_multiplier[i][0] != 0 || indspec->input_cargo_multiplier[i][1] != 0)) {
+ break;
+ }
+ }
+
+ /* Check if matching cargo has been found */
+ if (i == lengthof(indspec->accepts_cargo)) continue;
+
+ uint dist = DistanceManhattan(ind->xy, xy);
+
+ if (dist < best_dist) {
best = ind;
+ best_dist = dist;
+ accepted_cargo_index = i;
}
}
/* Found one? */
if (best != NULL) {
+ indspec = GetIndustrySpec(best->type);
best->was_cargo_delivered = true;
- best->cargo_waiting[0] = min(best->cargo_waiting[0] + num_pieces, 0xFFFF);
+ best->cargo_waiting[0] = min(best->cargo_waiting[0] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][0] / 256), 0xFFFF);
+ best->cargo_waiting[1] = min(best->cargo_waiting[1] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][1] / 256), 0xFFFF);
}
}
@@ -1171,213 +1196,222 @@
return profit;
}
-/*
- * Returns true if Vehicle v should wait loading because other vehicle is
- * already loading the same cargo type
- * v = vehicle to load, u = GetFirstInChain(v)
+/**
+ * Performs the vehicle payment _and_ marks the vehicle to be unloaded.
+ * @param front_v the vehicle to be unloaded
*/
-static bool LoadWait(const Vehicle* v, const Vehicle* u)
+void VehiclePayment(Vehicle *front_v)
{
- const Vehicle *w;
- bool has_any_cargo = false;
-
- if (!(u->current_order.flags & OF_FULL_LOAD)) return false;
+ int result = 0;
- for (w = u; w != NULL; w = w->next) {
- if (w->cargo_count != 0) {
- if (v->cargo_type == w->cargo_type &&
- u->last_station_visited == w->cargo_source) {
- return false;
+ int profit = 0;
+ int total_veh_profit = 0; // accumulates the profit across the vehicle chain (used by trains)
+ int32 route_profit = 0; // the grand total amount for the route. A-D of transfer chain A-B-C-D
+ int virtual_profit = 0; // virtual profit of one vehicle element for feeder systems
+ int virtual_profit_total = 0; // virtual profit for entire vehicle chain
+ int total_cargo_feeder_share = 0; // the feeder cash amount for the goods being loaded/unloaded in this load step
+
+ int all_vehicles_cargo_feeder_share = front_v->cargo_feeder_share; // used to hold transfer value of complete vehicle chain - used by trains
+
+ StationID last_visited = front_v->last_station_visited;
+ Station *st = GetStation(last_visited);
+
+ /* The owner of the train wants to be paid */
+ PlayerID old_player = _current_player;
+ _current_player = front_v->owner;
+
+ /* At this moment loading cannot be finished */
+ CLRBIT(front_v->vehicle_flags, VF_LOADING_FINISHED);
+
+ /* Start unloading in at the first possible moment */
+ front_v->load_unload_time_rem = 1;
+
+ for (Vehicle *v = front_v; v != NULL; v = v->next) {
+ /* No cargo to unload */
+ if (v->cargo_cap == 0 || v->cargo_count == 0) continue;
+
+ SETBIT(v->vehicle_flags, VF_CARGO_UNLOADING);
+ /* All cargo has already been paid for, no need to pay again */
+ if (v->cargo_count == v->cargo_paid_for) continue;
+
+ GoodsEntry *ge = &st->goods[v->cargo_type];
+
+ if (v->cargo_source != last_visited &&
+ HASBIT(ge->waiting_acceptance, 15) &&
+ (front_v->current_order.flags & OF_TRANSFER) == 0) {
+ /* Deliver goods to the station */
+ st->time_since_unload = 0;
+
+ /* handle end of route payment */
+ profit += DeliverGoods(v->cargo_count - v->cargo_paid_for, v->cargo_type, v->cargo_source, last_visited, v->cargo_source_xy, v->cargo_days);
+ v->cargo_paid_for = v->cargo_count;
+ route_profit = profit; // display amount paid for final route delivery, A-D of a chain A-B-C-D
+ total_veh_profit = profit - all_vehicles_cargo_feeder_share; // whole vehicle is not payed for transfers picked up earlier
+ total_cargo_feeder_share = -all_vehicles_cargo_feeder_share; // total of transfer fees in vehicle chain needs to be zero at end of unload
+
+ v->cargo_feeder_share = 0; // clear transfer cost per vehicle
+ result |= 1;
+ } else if (front_v->current_order.flags & (OF_UNLOAD | OF_TRANSFER)) {
+ if ((front_v->current_order.flags & OF_TRANSFER) != 0) {
+ virtual_profit = GetTransportedGoodsIncome(
+ v->cargo_count - v->cargo_paid_for,
+ /* pay transfer vehicle for only the part of transfer it has done: ie. cargo_loaded_at_xy to here */
+ DistanceManhattan(v->cargo_loaded_at_xy, GetStation(last_visited)->xy),
+ v->cargo_days,
+ v->cargo_type);
+
+ front_v->profit_this_year += virtual_profit;
+ ge->feeder_profit += v->cargo_feeder_share + virtual_profit; // transfer cargo transfer fees to station
+ total_cargo_feeder_share -= v->cargo_feeder_share; // accumulate deduction of feeder shares
+ v->cargo_feeder_share = 0; // clear transfer cost
+
+ /* keep total of cargo unloaded (pending) for accurate cargoshare calculation on load */
+ SB(ge->unload_pending, 0, 12, GB(ge->unload_pending, 0, 12) + v->cargo_count);
+
+ virtual_profit_total += virtual_profit; // accumulate transfer profits for whole vehicle
+ v->cargo_paid_for = v->cargo_count; // record how much of the cargo has been paid for to eliminate double counting
}
- has_any_cargo = true;
+ result |= 2;
}
}
- const Station *st = GetStation(u->last_station_visited);
- std::list<Vehicle *>::const_iterator iter;
- for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
- const Vehicle *x = *iter;
- if (!(x->vehstatus & (VS_STOPPED | VS_CRASHED)) && u != x) {
- bool other_has_any_cargo = false;
- bool has_space_for_same_type = false;
- bool other_has_same_type = false;
-
- for (w = x; w != NULL; w = w->next) {
- if (w->cargo_count < w->cargo_cap && v->cargo_type == w->cargo_type) {
- has_space_for_same_type = true;
- }
+ /* Ensure a negative total is only applied to the vehicle if there is value to reduce. */
+ front_v->cargo_feeder_share = max(front_v->cargo_feeder_share + total_cargo_feeder_share, 0);
- if (w->cargo_count != 0) {
- if (v->cargo_type == w->cargo_type &&
- u->last_station_visited == w->cargo_source) {
- other_has_same_type = true;
- }
- other_has_any_cargo = true;
- }
- }
-
- if (has_space_for_same_type) {
- if (other_has_same_type) return true;
- if (other_has_any_cargo && !has_any_cargo) return true;
- }
- }
+ if (virtual_profit_total > 0) {
+ ShowFeederIncomeAnimation(front_v->x_pos, front_v->y_pos, front_v->z_pos, virtual_profit_total);
}
- return false;
+ if (route_profit != 0) {
+ front_v->profit_this_year += total_veh_profit;
+ SubtractMoneyFromPlayer(-route_profit);
+
+ if (IsLocalPlayer() && !PlayVehicleSound(front_v, VSE_LOAD_UNLOAD)) {
+ SndPlayVehicleFx(SND_14_CASHTILL, front_v);
+ }
+
+ ShowCostOrIncomeAnimation(front_v->x_pos, front_v->y_pos, front_v->z_pos, -total_veh_profit);
+ }
+
+ _current_player = old_player;
}
-int LoadUnloadVehicle(Vehicle *v, bool just_arrived)
+/**
+ * Loads/unload the vehicle if possible.
+ * @param v the vehicle to be (un)loaded
+ * @param cargo_left the amount of each cargo type that is
+ * virtually left on the platform to be
+ * picked up by another vehicle when all
+ * previous vehicles have loaded.
+ */
+static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
{
- int profit = 0;
- int total_veh_profit = 0; // accumulates the profit across the vehicle chain (used by trains)
- int32 route_profit = 0; // the grand total amount for the route. A-D of transfer chain A-B-C-D
- int virtual_profit = 0; // virtual profit of one vehicle element for feeder systems
- int virtual_profit_total = 0; // virtual profit for entire vehicle chain
- int total_cargo_feeder_share = 0; // the feeder cash amount for the goods being loaded/unloaded in this load step
+ assert(v->current_order.type == OT_LOADING);
- int unloading_time = 20;
+ /* We have not waited enough time till the next round of loading/unloading */
+ if (--v->load_unload_time_rem != 0) {
+ if (_patches.improved_load && HASBIT(v->current_order.flags, OFB_FULL_LOAD)) {
+ /* 'Reserve' this cargo for this vehicle, because we were first. */
+ for (; v != NULL; v = v->next) {
+ if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo_count;
+ }
+ }
+ return;
+ }
+
+ int unloading_time = 0;
Vehicle *u = v;
int result = 0;
- int t;
- uint count, cap;
- PlayerID old_player;
- bool completely_empty = true;
- byte load_amount;
- bool anything_loaded = false;
+ int cap;
- assert(v->current_order.type == OT_LOADING);
+ bool completely_empty = true;
+ bool anything_unloaded = false;
+ bool anything_loaded = false;
+ uint32 cargo_not_full = 0;
+ uint32 cargo_full = 0;
+ int total_cargo_feeder_share = 0; // the feeder cash amount for the goods being loaded/unloaded in this load step
v->cur_speed = 0;
- /* Loading can only have finished when all the cargo has been unloaded, and
- * there is nothing left to load. It's easier to clear this if the
- * conditions haven't been met than attempting to check them all before
- * enabling though. */
- SETBIT(v->vehicle_flags, VF_LOADING_FINISHED);
-
- old_player = _current_player;
- _current_player = v->owner;
-
StationID last_visited = v->last_station_visited;
Station *st = GetStation(last_visited);
- int all_vehicles_cargo_feeder_share = v->cargo_feeder_share; // used to hold transfer value of complete vehicle chain - used by trains
+ for (; v != NULL; v = v->next) {
+ if (v->cargo_cap == 0) continue;
- for (; v != NULL; v = v->next) {
- GoodsEntry* ge;
- load_amount = EngInfo(v->engine_type)->load_amount;
+ byte load_amount = EngInfo(v->engine_type)->load_amount;
if (_patches.gradual_loading && HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_LOAD_AMOUNT)) {
uint16 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v);
if (cb_load_amount != CALLBACK_FAILED) load_amount = cb_load_amount & 0xFF;
}
- if (v->cargo_cap == 0) continue;
-
- /* If the vehicle has just arrived, set it to unload. */
- if (just_arrived) SETBIT(v->vehicle_flags, VF_CARGO_UNLOADING);
+ GoodsEntry *ge = &st->goods[v->cargo_type];
+ int count = GB(ge->waiting_acceptance, 0, 12);
- ge = &st->goods[v->cargo_type];
- count = GB(ge->waiting_acceptance, 0, 12);
-
- /* unload? */
- if (v->cargo_count != 0 && HASBIT(v->vehicle_flags, VF_CARGO_UNLOADING)) {
+ if (HASBIT(v->vehicle_flags, VF_CARGO_UNLOADING)) {
uint16 amount_unloaded = _patches.gradual_loading ? min(v->cargo_count, load_amount) : v->cargo_count;
- CLRBIT(u->vehicle_flags, VF_LOADING_FINISHED);
-
if (v->cargo_source != last_visited && ge->waiting_acceptance & 0x8000 && !(u->current_order.flags & OF_TRANSFER)) {
- /* deliver goods to the station */
- st->time_since_unload = 0;
-
- unloading_time += v->cargo_count; // TTDBUG: bug in original TTD
-
- /* handle end of route payment */
- if (just_arrived && v->cargo_paid_for < v->cargo_count) {
- profit += DeliverGoods(v->cargo_count - v->cargo_paid_for, v->cargo_type, v->cargo_source, last_visited, v->cargo_source_xy, v->cargo_days);
- v->cargo_paid_for = v->cargo_count;
- route_profit = profit; // display amount paid for final route delivery, A-D of a chain A-B-C-D
- total_veh_profit = profit - all_vehicles_cargo_feeder_share; // whole vehicle is not payed for transfers picked up earlier
- total_cargo_feeder_share = -all_vehicles_cargo_feeder_share; // total of transfer fees in vehicle chain needs to be zero at end of unload
- v->cargo_feeder_share = 0; // clear transfer cost per vehicle
- }
result |= 1;
- v->cargo_count -= amount_unloaded;
- v->cargo_paid_for -= min(amount_unloaded, v->cargo_paid_for);
- if (_patches.gradual_loading) continue;
-
} else if (u->current_order.flags & (OF_UNLOAD | OF_TRANSFER)) {
-
- /* unload goods and let it wait at the station */
- st->time_since_unload = 0;
-
- /* handle transfer */
- if (just_arrived && (u->current_order.flags & OF_TRANSFER) && v->cargo_paid_for < v->cargo_count) {
- virtual_profit = GetTransportedGoodsIncome(
- v->cargo_count - v->cargo_paid_for,
- /* pay transfer vehicle for only the part of transfer it has done: ie. cargo_loaded_at_xy to here */
- DistanceManhattan(v->cargo_loaded_at_xy, GetStation(last_visited)->xy),
- v->cargo_days,
- v->cargo_type);
-
- ge->feeder_profit += v->cargo_feeder_share; // transfer cargo transfer fees to station
- total_cargo_feeder_share -= v->cargo_feeder_share; // accumulate deduction of feeder shares
- v->cargo_feeder_share = 0; // clear transfer cost
-
- /* keep total of cargo unloaded (pending) for accurate cargoshare calculation on load */
- SB(ge->unload_pending, 0, 12, GB(ge->unload_pending, 0, 12) + v->cargo_count);
-
- virtual_profit_total += virtual_profit; // accumulate transfer profits for whole vehicle
- v->cargo_paid_for = v->cargo_count; // record how much of the cargo has been paid for to eliminate double counting
- }
-
- unloading_time += v->cargo_count;
- t = GB(ge->waiting_acceptance, 0, 12);
- if (t == 0) {
+ if (count == 0) {
/* No goods waiting at station */
- ge->enroute_time = v->cargo_days;
- ge->enroute_from = v->cargo_source;
+ ge->enroute_time = v->cargo_days;
+ ge->enroute_from = v->cargo_source;
ge->enroute_from_xy = v->cargo_source_xy;
} else {
/* Goods already waiting at station. Set counters to the worst value. */
if (v->cargo_days >= ge->enroute_time) ge->enroute_time = v->cargo_days;
if (last_visited != ge->enroute_from) {
- ge->enroute_from = v->cargo_source;
+ ge->enroute_from = v->cargo_source;
ge->enroute_from_xy = v->cargo_source_xy;
}
}
- /* Update amount of waiting cargo */
- SB(ge->waiting_acceptance, 0, 12, min(amount_unloaded + t, 0xFFF));
+ /* Update amount of waiting cargo. There is, however, no sense in
+ * updating the count variable because this vehicle will not be
+ * able to take the cargo. */
+ SB(ge->waiting_acceptance, 0, 12, min(amount_unloaded + count, 0xFFF));
/* if there is not enough to unload from pending, ensure it does not go -ve
* else deduct amount actually unloaded from unload_pending */
SB(ge->unload_pending, 0, 12, max(GB(ge->unload_pending, 0, 12) - amount_unloaded, 0U));
- if (u->current_order.flags & OF_TRANSFER) {
- ge->feeder_profit += virtual_profit;
- u->profit_this_year += virtual_profit;
- }
result |= 2;
- v->cargo_count -= amount_unloaded;
- v->cargo_paid_for -= min(amount_unloaded, v->cargo_paid_for);
- if (_patches.gradual_loading) continue;
+ } else {
+ /* The order changed while unloading (unset unload/transfer) or the
+ * station does not accept goods anymore. */
+ CLRBIT(v->vehicle_flags, VF_CARGO_UNLOADING);
+ continue;
}
- if (v->cargo_count != 0) completely_empty = false;
- }
+ /* Deliver goods to the station */
+ st->time_since_unload = 0;
- /* The vehicle must have been unloaded because it is either empty, or
- * the UNLOADING bit is already clear in v->vehicle_flags. */
- CLRBIT(v->vehicle_flags, VF_CARGO_UNLOADING);
+ unloading_time += amount_unloaded;
+
+ v->cargo_count -= amount_unloaded;
+ v->cargo_paid_for -= min(amount_unloaded, v->cargo_paid_for);
+
+ anything_unloaded = true;
+ if (_patches.gradual_loading && v->cargo_count != 0) {
+ completely_empty = false;
+ } else {
+ /* We have finished unloading (cargo count == 0) */
+ CLRBIT(v->vehicle_flags, VF_CARGO_UNLOADING);
+ }
+
+ continue;
+ }
/* We cannot have paid for more cargo than there is on board. */
assert(v->cargo_paid_for <= v->cargo_count);
- /* don't pick up goods that we unloaded */
+ /* Do not pick up goods that we unloaded */
if (u->current_order.flags & OF_UNLOAD) continue;
/* update stats */
- ge->days_since_pickup = 0;
+ int t;
switch (u->type) {
case VEH_TRAIN: t = u->u.rail.cached_max_speed; break;
case VEH_ROAD: t = u->max_speed / 2; break;
@@ -1385,6 +1419,7 @@
}
/* if last speed is 0, we treat that as if no vehicle has ever visited the station. */
+ ge->days_since_pickup = 0;
ge->last_speed = min(t, 255);
ge->last_age = _cur_year - v->build_year;
@@ -1393,11 +1428,22 @@
if (count != 0 &&
(cap = v->cargo_cap - v->cargo_count) != 0) {
- if (v->cargo_count == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
-
/* Skip loading this vehicle if another train/vehicle is already handling
* the same cargo type at this station */
- if (_patches.improved_load && (u->current_order.flags & OF_FULL_LOAD) && LoadWait(v,u)) continue;
+ if (_patches.improved_load && cargo_left[v->cargo_type] < 0) {
+ SETBIT(cargo_not_full, v->cargo_type);
+ continue;
+ }
+
+ if (cap > count) cap = count;
+ if (_patches.gradual_loading) cap = min(cap, load_amount);
+ if (_patches.improved_load) {
+ /* Don't load stuff that is already 'reserved' for other vehicles */
+ cap = min(cargo_left[v->cargo_type], cap);
+ cargo_left[v->cargo_type] -= cap;
+ }
+
+ if (v->cargo_count == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
/* TODO: Regarding this, when we do gradual loading, we
* should first unload all vehicles and then start
@@ -1409,10 +1455,6 @@
completely_empty = false;
anything_loaded = true;
- if (cap > count) cap = count;
- if (_patches.gradual_loading) cap = min(cap, load_amount);
- if (cap < count) CLRBIT(u->vehicle_flags, VF_LOADING_FINISHED);
-
/* cargoshare is proportioned by the amount due to unload
* Otherwise, with gradual loading, 100% of credits would be taken immediately,
* even if the cargo volume represents a tiny percent of the whole.
@@ -1437,31 +1479,54 @@
result |= 2;
st->last_vehicle_type = v->type;
}
+
+ if (v->cargo_count == v->cargo_cap) {
+ SETBIT(cargo_full, v->cargo_type);
+ } else {
+ SETBIT(cargo_not_full, v->cargo_type);
+ }
+ }
+
+ /* We update these variables here, so gradual loading still fills
+ * all wagons at the same time instead of using the same 'improved'
+ * loading algorithm for the wagons (only fill wagon when there is
+ * enough to fill the previous wagons) */
+ if (_patches.improved_load && HASBIT(u->current_order.flags, OFB_FULL_LOAD)) {
+ /* Update left cargo */
+ for (v = u; v != NULL; v = v->next) {
+ if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo_count;
+ }
}
v = u;
- /* Ensure a negative total is only applied to the vehicle if there is value to reduce. */
- if (!((v->cargo_feeder_share == 0) && (total_cargo_feeder_share < 0)))
- v->cargo_feeder_share += total_cargo_feeder_share;
+ v->cargo_feeder_share += total_cargo_feeder_share;
- if (_patches.gradual_loading) {
- /* The time it takes to load one 'slice' of cargo or passengers depends
- * on the vehicle type - the values here are those found in TTDPatch */
- uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
+ if (anything_loaded || anything_unloaded) {
+ if (_patches.gradual_loading) {
+ /* The time it takes to load one 'slice' of cargo or passengers depends
+ * on the vehicle type - the values here are those found in TTDPatch */
+ const uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
- unloading_time = gradual_loading_wait_time[v->type];
- if (HASBIT(v->vehicle_flags, VF_LOADING_FINISHED)) {
- if (anything_loaded) {
- unloading_time += 20;
- } else {
- unloading_time = 20;
+ unloading_time = gradual_loading_wait_time[v->type];
+ }
+ } else {
+ bool finished_loading = true;
+ if (HASBIT(v->current_order.flags, OFB_FULL_LOAD)) {
+ if (_patches.full_load_any) {
+ /* if the aircraft carries passengers and is NOT full, then
+ * continue loading, no matter how much mail is in */
+ if ((v->type == VEH_AIRCRAFT && IsCargoInClass(v->cargo_type, CC_PASSENGERS) && v->cargo_cap != v->cargo_count) ||
+ (cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) { // There are stull non-full cargos
+ finished_loading = false;
+ }
+ } else if (cargo_not_full != 0) {
+ finished_loading = false;
}
}
- }
+ unloading_time = 20;
- if (virtual_profit_total > 0) {
- ShowFeederIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, virtual_profit_total);
+ SB(v->vehicle_flags, VF_LOADING_FINISHED, 1, finished_loading);
}
if (v->type == VEH_TRAIN) {
@@ -1480,25 +1545,32 @@
}
if (result != 0) {
+ InvalidateWindow(v->GetVehicleListWindowClass(), v->owner);
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
+
st->MarkTilesDirty();
+ v->MarkDirty();
if (result & 2) InvalidateWindow(WC_STATION_VIEW, last_visited);
-
- if (route_profit != 0) {
- v->profit_this_year += total_veh_profit;
- SubtractMoneyFromPlayer(-route_profit);
+ }
+}
- if (IsLocalPlayer() && !PlayVehicleSound(v, VSE_LOAD_UNLOAD)) {
- SndPlayVehicleFx(SND_14_CASHTILL, v);
- }
+/**
+ * Load/unload the vehicles in this station according to the order
+ * they entered.
+ * @param st the station to do the loading/unloading for
+ */
+void LoadUnloadStation(Station *st)
+{
+ int cargo_left[NUM_CARGO];
- ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, -total_veh_profit);
- }
+ for (uint i = 0; i < NUM_CARGO; i++) cargo_left[i] = GB(st->goods[i].waiting_acceptance, 0, 12);
+
+ std::list<Vehicle *>::iterator iter;
+ for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
+ Vehicle *v = *iter;
+ if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) LoadUnloadVehicle(v, cargo_left);
}
-
- _current_player = old_player;
- return result;
}
void PlayersMonthlyLoop()