diff options
-rw-r--r-- | src/economy.cpp | 154 |
1 files changed, 92 insertions, 62 deletions
diff --git a/src/economy.cpp b/src/economy.cpp index 6b8280587..111903163 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -1378,15 +1378,98 @@ static bool LoadWait(const Vehicle* v, const Vehicle* u) return false; } -int LoadUnloadVehicle(Vehicle *v, bool just_arrived) +/** + * Performs the vehicle payment _and_ marks the vehicle to be unloaded. + * @param front_v the vehicle to be unloaded + * @return what windows need to be updated; + * bit 0 set: only vehicle details, + * bit 1 set: vehicle details and station details + */ +static int VehiclePayment(Vehicle *front_v) { + int result = 0; + 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 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); + + for (Vehicle *v = front_v; v != NULL; v = v->next) { + if (v->cargo_cap == 0) continue; + + SETBIT(v->vehicle_flags, VF_CARGO_UNLOADING); + 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); + + 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 + } + result |= 2; + } + } + + /* 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 (virtual_profit_total > 0) { + ShowFeederIncomeAnimation(front_v->x_pos, front_v->y_pos, front_v->z_pos, virtual_profit_total); + } + + 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); + } + + return result; +} +int LoadUnloadVehicle(Vehicle *v, bool just_arrived) +{ int unloading_time = 20; Vehicle *u = v; int result = 0; @@ -1396,6 +1479,7 @@ int LoadUnloadVehicle(Vehicle *v, bool just_arrived) bool completely_empty = true; byte load_amount; bool anything_loaded = false; + 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); @@ -1413,7 +1497,7 @@ int LoadUnloadVehicle(Vehicle *v, bool just_arrived) 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 + if (just_arrived) result |= VehiclePayment(v); for (; v != NULL; v = v->next) { GoodsEntry* ge; @@ -1425,9 +1509,6 @@ int LoadUnloadVehicle(Vehicle *v, bool just_arrived) 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); - ge = &st->goods[v->cargo_type]; count = GB(ge->waiting_acceptance, 0, 12); @@ -1443,45 +1524,15 @@ int LoadUnloadVehicle(Vehicle *v, bool just_arrived) 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) { @@ -1505,10 +1556,6 @@ int LoadUnloadVehicle(Vehicle *v, bool just_arrived) * 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); @@ -1593,9 +1640,7 @@ int LoadUnloadVehicle(Vehicle *v, bool just_arrived) 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 @@ -1612,10 +1657,6 @@ int LoadUnloadVehicle(Vehicle *v, bool just_arrived) } } - if (virtual_profit_total > 0) { - ShowFeederIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, virtual_profit_total); - } - if (v->type == VEH_TRAIN) { /* Each platform tile is worth 2 rail vehicles. */ int overhang = v->u.rail.cached_total_length - st->GetPlatformLength(v->tile) * TILE_SIZE; @@ -1636,17 +1677,6 @@ int LoadUnloadVehicle(Vehicle *v, bool just_arrived) st->MarkTilesDirty(); 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); - } - - ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, -total_veh_profit); - } } _current_player = old_player; |