src/economy.cpp
branchcpp_gui
changeset 6285 187e3ef04cc9
parent 6268 4b5241e5dd10
child 6298 c30fe89622df
equal deleted inserted replaced
6284:45d0233e7d79 6285:187e3ef04cc9
    34 #include "newgrf_sound.h"
    34 #include "newgrf_sound.h"
    35 #include "newgrf_callbacks.h"
    35 #include "newgrf_callbacks.h"
    36 #include "unmovable.h"
    36 #include "unmovable.h"
    37 #include "date.h"
    37 #include "date.h"
    38 #include "cargotype.h"
    38 #include "cargotype.h"
       
    39 #include "player_face.h"
    39 
    40 
    40 /* Score info */
    41 /* Score info */
    41 const ScoreInfo _score_info[] = {
    42 const ScoreInfo _score_info[] = {
    42 	{ SCORE_VEHICLES,        120, 100 },
    43 	{ SCORE_VEHICLES,        120, 100 },
    43 	{ SCORE_STATIONS,         80, 100 },
    44 	{ SCORE_STATIONS,         80, 100 },
  1328 }
  1329 }
  1329 
  1330 
  1330 int LoadUnloadVehicle(Vehicle *v, bool just_arrived)
  1331 int LoadUnloadVehicle(Vehicle *v, bool just_arrived)
  1331 {
  1332 {
  1332 	int profit = 0;
  1333 	int profit = 0;
  1333 	int v_profit = 0; //virtual profit for feeder systems
  1334 	int total_veh_profit = 0;      // accumulates the profit across the vehicle chain (used by trains)
  1334 	int v_profit_total = 0;
  1335 	int32 route_profit = 0;        // the grand total amount for the route. A-D of transfer chain A-B-C-D
       
  1336 	int virtual_profit = 0;        // virtual profit of one vehicle element for feeder systems
       
  1337 	int virtual_profit_total = 0;  // virtual profit for entire vehicle chain
       
  1338 	int total_cargo_feeder_share = 0;  // the feeder cash amount for the goods being loaded/unloaded in this load step
       
  1339 
  1335 	int unloading_time = 20;
  1340 	int unloading_time = 20;
  1336 	Vehicle *u = v;
  1341 	Vehicle *u = v;
  1337 	int result = 0;
  1342 	int result = 0;
  1338 	StationID last_visited;
       
  1339 	Station *st;
       
  1340 	int t;
  1343 	int t;
  1341 	uint count, cap;
  1344 	uint count, cap;
  1342 	PlayerID old_player;
  1345 	PlayerID old_player;
  1343 	bool completely_empty = true;
  1346 	bool completely_empty = true;
  1344 	byte load_amount;
  1347 	byte load_amount;
  1350 
  1353 
  1351 	/* Loading can only have finished when all the cargo has been unloaded, and
  1354 	/* Loading can only have finished when all the cargo has been unloaded, and
  1352 	 * there is nothing left to load. It's easier to clear this if the
  1355 	 * there is nothing left to load. It's easier to clear this if the
  1353 	 * conditions haven't been met than attempting to check them all before
  1356 	 * conditions haven't been met than attempting to check them all before
  1354 	 * enabling though. */
  1357 	 * enabling though. */
  1355 	SETBIT(v->load_status, LS_LOADING_FINISHED);
  1358 	SETBIT(v->vehicle_flags, VF_LOADING_FINISHED);
  1356 
  1359 
  1357 	old_player = _current_player;
  1360 	old_player = _current_player;
  1358 	_current_player = v->owner;
  1361 	_current_player = v->owner;
  1359 
  1362 
  1360 	last_visited = v->last_station_visited;
  1363 	StationID last_visited = v->last_station_visited;
  1361 	st = GetStation(last_visited);
  1364 	Station *st = GetStation(last_visited);
       
  1365 
       
  1366 	int all_vehicles_cargo_feeder_share = v->cargo_feeder_share; // used to hold transfer value of complete vehicle chain - used by trains
  1362 
  1367 
  1363 	for (; v != NULL; v = v->next) {
  1368 	for (; v != NULL; v = v->next) {
  1364 		GoodsEntry* ge;
  1369 		GoodsEntry* ge;
  1365 		load_amount = EngInfo(v->engine_type)->load_amount;
  1370 		load_amount = EngInfo(v->engine_type)->load_amount;
  1366 		if (_patches.gradual_loading) {
  1371 		if (_patches.gradual_loading) {
  1369 		}
  1374 		}
  1370 
  1375 
  1371 		if (v->cargo_cap == 0) continue;
  1376 		if (v->cargo_cap == 0) continue;
  1372 
  1377 
  1373 		/* If the vehicle has just arrived, set it to unload. */
  1378 		/* If the vehicle has just arrived, set it to unload. */
  1374 		if (just_arrived) SETBIT(v->load_status, LS_CARGO_UNLOADING);
  1379 		if (just_arrived) SETBIT(v->vehicle_flags, VF_CARGO_UNLOADING);
  1375 
  1380 
  1376 		ge = &st->goods[v->cargo_type];
  1381 		ge = &st->goods[v->cargo_type];
  1377 		count = GB(ge->waiting_acceptance, 0, 12);
  1382 		count = GB(ge->waiting_acceptance, 0, 12);
  1378 
  1383 
  1379 		/* unload? */
  1384 		/* unload? */
  1380 		if (v->cargo_count != 0 && HASBIT(v->load_status, LS_CARGO_UNLOADING)) {
  1385 		if (v->cargo_count != 0 && HASBIT(v->vehicle_flags, VF_CARGO_UNLOADING)) {
  1381 			uint16 amount_unloaded = _patches.gradual_loading ? min(v->cargo_count, load_amount) : v->cargo_count;
  1386 			uint16 amount_unloaded = _patches.gradual_loading ? min(v->cargo_count, load_amount) : v->cargo_count;
  1382 
  1387 
  1383 			CLRBIT(u->load_status, LS_LOADING_FINISHED);
  1388 			CLRBIT(u->vehicle_flags, VF_LOADING_FINISHED);
  1384 
  1389 
  1385 			if (v->cargo_source != last_visited && ge->waiting_acceptance & 0x8000 && !(u->current_order.flags & OF_TRANSFER)) {
  1390 			if (v->cargo_source != last_visited && ge->waiting_acceptance & 0x8000 && !(u->current_order.flags & OF_TRANSFER)) {
  1386 				/* deliver goods to the station */
  1391 				/* deliver goods to the station */
  1387 				st->time_since_unload = 0;
  1392 				st->time_since_unload = 0;
  1388 
  1393 
  1389 				unloading_time += v->cargo_count; // TTDBUG: bug in original TTD
  1394 				unloading_time += v->cargo_count; // TTDBUG: bug in original TTD
       
  1395 
       
  1396 				/* handle end of route payment */
  1390 				if (just_arrived && v->cargo_paid_for < v->cargo_count) {
  1397 				if (just_arrived && v->cargo_paid_for < v->cargo_count) {
  1391 					profit += DeliverGoods(v->cargo_count - v->cargo_paid_for, v->cargo_type, v->cargo_source, last_visited, v->cargo_source_xy, v->cargo_days);
  1398 					profit += DeliverGoods(v->cargo_count - v->cargo_paid_for, v->cargo_type, v->cargo_source, last_visited, v->cargo_source_xy, v->cargo_days);
  1392 					v->cargo_paid_for = v->cargo_count;
  1399 					v->cargo_paid_for = v->cargo_count;
       
  1400 					route_profit = profit;       // display amount paid for final route delivery, A-D of a chain A-B-C-D
       
  1401 					total_veh_profit = profit - all_vehicles_cargo_feeder_share;  // whole vehicle is not payed for transfers picked up earlier
       
  1402 					total_cargo_feeder_share = -all_vehicles_cargo_feeder_share;  // total of transfer fees in vehicle chain needs to be zero at end of unload
       
  1403 					v->cargo_feeder_share = 0;   // clear transfer cost per vehicle
  1393 				}
  1404 				}
  1394 				result |= 1;
  1405 				result |= 1;
  1395 				v->cargo_count -= amount_unloaded;
  1406 				v->cargo_count -= amount_unloaded;
  1396 				v->cargo_paid_for -= min(amount_unloaded, v->cargo_paid_for);
  1407 				v->cargo_paid_for -= min(amount_unloaded, v->cargo_paid_for);
  1397 				if (_patches.gradual_loading) continue;
  1408 				if (_patches.gradual_loading) continue;
       
  1409 
  1398 			} else if (u->current_order.flags & (OF_UNLOAD | OF_TRANSFER)) {
  1410 			} else if (u->current_order.flags & (OF_UNLOAD | OF_TRANSFER)) {
       
  1411 
  1399 				/* unload goods and let it wait at the station */
  1412 				/* unload goods and let it wait at the station */
  1400 				st->time_since_unload = 0;
  1413 				st->time_since_unload = 0;
       
  1414 
       
  1415 				/* handle transfer */
  1401 				if (just_arrived && (u->current_order.flags & OF_TRANSFER) && v->cargo_paid_for < v->cargo_count) {
  1416 				if (just_arrived && (u->current_order.flags & OF_TRANSFER) && v->cargo_paid_for < v->cargo_count) {
  1402 					v_profit = GetTransportedGoodsIncome(
  1417 					virtual_profit = GetTransportedGoodsIncome(
  1403 						v->cargo_count - v->cargo_paid_for,
  1418 						v->cargo_count - v->cargo_paid_for,
  1404 						DistanceManhattan(v->cargo_source_xy, GetStation(last_visited)->xy),
  1419 						/* pay transfer vehicle for only the part of transfer it has done: ie. cargo_loaded_at_xy to here */
       
  1420 						DistanceManhattan(v->cargo_loaded_at_xy, GetStation(last_visited)->xy),
  1405 						v->cargo_days,
  1421 						v->cargo_days,
  1406 						v->cargo_type) * 3 / 2;
  1422 						v->cargo_type);
  1407 
  1423 
  1408 					v_profit_total += v_profit;
  1424 					ge->feeder_profit += v->cargo_feeder_share;         // transfer cargo transfer fees to station
  1409 					v->cargo_paid_for = v->cargo_count;
  1425 					total_cargo_feeder_share -= v->cargo_feeder_share;  // accumulate deduction of feeder shares
       
  1426 					v->cargo_feeder_share = 0;                          // clear transfer cost
       
  1427 
       
  1428 					/* keep total of cargo unloaded (pending) for accurate cargoshare calculation on load */
       
  1429 					SB(ge->unload_pending, 0, 12, GB(ge->unload_pending, 0, 12) + v->cargo_count);
       
  1430 
       
  1431 					virtual_profit_total += virtual_profit;   // accumulate transfer profits for whole vehicle
       
  1432 					v->cargo_paid_for = v->cargo_count;       // record how much of the cargo has been paid for to eliminate double counting
  1410 				}
  1433 				}
  1411 
  1434 
  1412 				unloading_time += v->cargo_count;
  1435 				unloading_time += v->cargo_count;
  1413 				t = GB(ge->waiting_acceptance, 0, 12);
  1436 				t = GB(ge->waiting_acceptance, 0, 12);
  1414 				if (t == 0) {
  1437 				if (t == 0) {
  1426 					}
  1449 					}
  1427 				}
  1450 				}
  1428 				/* Update amount of waiting cargo */
  1451 				/* Update amount of waiting cargo */
  1429 				SB(ge->waiting_acceptance, 0, 12, min(amount_unloaded + t, 0xFFF));
  1452 				SB(ge->waiting_acceptance, 0, 12, min(amount_unloaded + t, 0xFFF));
  1430 
  1453 
       
  1454 				/* if there is not enough to unload from pending, ensure it does not go -ve
       
  1455 				 * else deduct amount actually unloaded from unload_pending */
       
  1456 				SB(ge->unload_pending, 0, 12, max(GB(ge->unload_pending, 0, 12) - amount_unloaded, 0U));
       
  1457 
  1431 				if (u->current_order.flags & OF_TRANSFER) {
  1458 				if (u->current_order.flags & OF_TRANSFER) {
  1432 					ge->feeder_profit += v_profit;
  1459 					ge->feeder_profit += virtual_profit;
  1433 					u->profit_this_year += v_profit;
  1460 					u->profit_this_year += virtual_profit;
  1434 				}
  1461 				}
  1435 				result |= 2;
  1462 				result |= 2;
  1436 				v->cargo_count -= amount_unloaded;
  1463 				v->cargo_count -= amount_unloaded;
  1437 				v->cargo_paid_for -= min(amount_unloaded, v->cargo_paid_for);
  1464 				v->cargo_paid_for -= min(amount_unloaded, v->cargo_paid_for);
  1438 				if (_patches.gradual_loading) continue;
  1465 				if (_patches.gradual_loading) continue;
  1440 
  1467 
  1441 			if (v->cargo_count != 0) completely_empty = false;
  1468 			if (v->cargo_count != 0) completely_empty = false;
  1442 		}
  1469 		}
  1443 
  1470 
  1444 		/* The vehicle must have been unloaded because it is either empty, or
  1471 		/* The vehicle must have been unloaded because it is either empty, or
  1445 		 * the UNLOADING bit is already clear in v->load_status. */
  1472 		 * the UNLOADING bit is already clear in v->vehicle_flags. */
  1446 		CLRBIT(v->load_status, LS_CARGO_UNLOADING);
  1473 		CLRBIT(v->vehicle_flags, VF_CARGO_UNLOADING);
  1447 
  1474 
  1448 		/* We cannot have paid for more cargo than there is on board. */
  1475 		/* We cannot have paid for more cargo than there is on board. */
  1449 		assert(v->cargo_paid_for <= v->cargo_count);
  1476 		assert(v->cargo_paid_for <= v->cargo_count);
  1450 
  1477 
  1451 		/* don't pick up goods that we unloaded */
  1478 		/* don't pick up goods that we unloaded */
  1465 
  1492 
  1466 		/* If there's goods waiting at the station, and the vehicle
  1493 		/* If there's goods waiting at the station, and the vehicle
  1467 		 * has capacity for it, load it on the vehicle. */
  1494 		 * has capacity for it, load it on the vehicle. */
  1468 		if (count != 0 &&
  1495 		if (count != 0 &&
  1469 				(cap = v->cargo_cap - v->cargo_count) != 0) {
  1496 				(cap = v->cargo_cap - v->cargo_count) != 0) {
  1470 			int cargoshare;
       
  1471 			int feeder_profit_share;
       
  1472 
  1497 
  1473 			if (v->cargo_count == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
  1498 			if (v->cargo_count == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
  1474 
  1499 
  1475 			/* Skip loading this vehicle if another train/vehicle is already handling
  1500 			/* Skip loading this vehicle if another train/vehicle is already handling
  1476 			 * the same cargo type at this station */
  1501 			 * the same cargo type at this station */
  1486 			completely_empty = false;
  1511 			completely_empty = false;
  1487 			anything_loaded = true;
  1512 			anything_loaded = true;
  1488 
  1513 
  1489 			if (cap > count) cap = count;
  1514 			if (cap > count) cap = count;
  1490 			if (_patches.gradual_loading) cap = min(cap, load_amount);
  1515 			if (_patches.gradual_loading) cap = min(cap, load_amount);
  1491 			if (cap < count) CLRBIT(u->load_status, LS_LOADING_FINISHED);
  1516 			if (cap < count) CLRBIT(u->vehicle_flags, VF_LOADING_FINISHED);
  1492 			cargoshare = cap * 10000 / ge->waiting_acceptance;
  1517 
  1493 			feeder_profit_share = ge->feeder_profit * cargoshare / 10000;
  1518 			/* cargoshare is proportioned by the amount due to unload
       
  1519 			 * Otherwise, with gradual loading, 100% of credits would be taken immediately,
       
  1520 			 * even if the cargo volume represents a tiny percent of the whole.
       
  1521 			 * ge->unload_pending holds the amount that has been credited, but has not yet been unloaded.
       
  1522 			 */
       
  1523 			int cargoshare = cap * 10000 / (ge->waiting_acceptance + ge->unload_pending);
       
  1524 			int feeder_profit_share = ge->feeder_profit * cargoshare / 10000;
  1494 			v->cargo_count += cap;
  1525 			v->cargo_count += cap;
  1495 			ge->waiting_acceptance -= cap;
  1526 			ge->waiting_acceptance -= cap;
  1496 			u->profit_this_year -= feeder_profit_share;
  1527 
       
  1528 			total_cargo_feeder_share += feeder_profit_share;    // store cost for later payment when cargo unloaded
       
  1529 			v->cargo_loaded_at_xy = st->xy;                     // retains location of where the cargo was picked up for intermediate payments
       
  1530 
  1497 			ge->feeder_profit -= feeder_profit_share;
  1531 			ge->feeder_profit -= feeder_profit_share;
  1498 			unloading_time += cap;
  1532 			unloading_time += cap;
  1499 			st->time_since_load = 0;
  1533 			st->time_since_load = 0;
  1500 
  1534 
  1501 			/* And record the source of the cargo, and the days in travel. */
  1535 			/* And record the source of the cargo, and the days in travel. */
  1507 		}
  1541 		}
  1508 	}
  1542 	}
  1509 
  1543 
  1510 	v = u;
  1544 	v = u;
  1511 
  1545 
       
  1546 	/* Ensure a negative total is only applied to the vehicle if there is value to reduce. */
       
  1547 	if (!((v->cargo_feeder_share == 0) && (total_cargo_feeder_share < 0)))
       
  1548 		v->cargo_feeder_share += total_cargo_feeder_share;
       
  1549 
  1512 	if (_patches.gradual_loading) {
  1550 	if (_patches.gradual_loading) {
  1513 		/* The time it takes to load one 'slice' of cargo or passengers depends
  1551 		/* The time it takes to load one 'slice' of cargo or passengers depends
  1514 		 * on the vehicle type - the values here are those found in TTDPatch */
  1552 		 * on the vehicle type - the values here are those found in TTDPatch */
  1515 		uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
  1553 		uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
  1516 
  1554 
  1517 		unloading_time = gradual_loading_wait_time[v->type];
  1555 		unloading_time = gradual_loading_wait_time[v->type];
  1518 		if (HASBIT(v->load_status, LS_LOADING_FINISHED)) {
  1556 		if (HASBIT(v->vehicle_flags, VF_LOADING_FINISHED)) {
  1519 			if (anything_loaded) {
  1557 			if (anything_loaded) {
  1520 				unloading_time += 20;
  1558 				unloading_time += 20;
  1521 			} else {
  1559 			} else {
  1522 				unloading_time = 20;
  1560 				unloading_time = 20;
  1523 			}
  1561 			}
  1524 		}
  1562 		}
  1525 	}
  1563 	}
  1526 
  1564 
  1527 	if (v_profit_total > 0) {
  1565 	if (virtual_profit_total > 0) {
  1528 		ShowFeederIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, v_profit_total);
  1566 		ShowFeederIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, virtual_profit_total);
  1529 	}
  1567 	}
  1530 
  1568 
  1531 	if (v->type == VEH_Train) {
  1569 	if (v->type == VEH_Train) {
  1532 		/* Each platform tile is worth 2 rail vehicles. */
  1570 		/* Each platform tile is worth 2 rail vehicles. */
  1533 		int overhang = v->u.rail.cached_total_length - st->GetPlatformLength(v->tile) * TILE_SIZE;
  1571 		int overhang = v->u.rail.cached_total_length - st->GetPlatformLength(v->tile) * TILE_SIZE;
  1547 		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
  1585 		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
  1548 		st->MarkTilesDirty();
  1586 		st->MarkTilesDirty();
  1549 
  1587 
  1550 		if (result & 2) InvalidateWindow(WC_STATION_VIEW, last_visited);
  1588 		if (result & 2) InvalidateWindow(WC_STATION_VIEW, last_visited);
  1551 
  1589 
  1552 		if (profit != 0) {
  1590 		if (route_profit != 0) {
  1553 			v->profit_this_year += profit;
  1591 			v->profit_this_year += total_veh_profit;
  1554 			SubtractMoneyFromPlayer(-profit);
  1592 			SubtractMoneyFromPlayer(-route_profit);
  1555 
  1593 
  1556 			if (IsLocalPlayer() && !PlayVehicleSound(v, VSE_LOAD_UNLOAD)) {
  1594 			if (IsLocalPlayer() && !PlayVehicleSound(v, VSE_LOAD_UNLOAD)) {
  1557 				SndPlayVehicleFx(SND_14_CASHTILL, v);
  1595 				SndPlayVehicleFx(SND_14_CASHTILL, v);
  1558 			}
  1596 			}
  1559 
  1597 
  1560 			ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, -profit);
  1598 			ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, -total_veh_profit);
  1561 		}
  1599 		}
  1562 	}
  1600 	}
  1563 
  1601 
  1564 	_current_player = old_player;
  1602 	_current_player = old_player;
  1565 	return result;
  1603 	return result;