54 #include "table/strings.h"
75 static inline int32
BigMulS(const int32 a, const int32 b, const uint8 shift)
77 return (int32)((int64)a * (int64)b >> shift);
101 Money _additional_cash_required;
102 static PriceMultipliers _price_base_multiplier;
120 FOR_ALL_STATIONS(st) {
124 Money value = num * _price[PR_STATION_VALUE] * 25;
128 if (v->
owner != owner)
continue;
134 value += v->
value * 3 >> 1;
158 memset(_score_part[owner], 0,
sizeof(_score_part[owner]));
163 Money min_profit = 0;
164 bool min_profit_first =
true;
168 if (v->
owner != owner)
continue;
175 min_profit_first =
false;
183 _score_part[owner][SCORE_VEHICLES] = num;
185 if (min_profit > 0) {
186 _score_part[owner][SCORE_MIN_PROFIT] =
ClampToI32(min_profit);
195 FOR_ALL_STATIONS(st) {
197 if (st->
owner == owner && (st->time_since_load <= 20 || st->time_since_unload <= 20)) num +=
CountBits((byte)st->
facilities);
199 _score_part[owner][SCORE_STATIONS] = num;
213 }
while (++cee, --numec);
215 if (min_income > 0) {
216 _score_part[owner][SCORE_MIN_INCOME] =
ClampToI32(min_income);
219 _score_part[owner][SCORE_MAX_INCOME] =
ClampToI32(max_income);
231 }
while (++cee, --numec);
233 _score_part[owner][SCORE_DELIVERED] =
ClampToI32(total_delivered);
263 s =
Clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].
score / _score_info[i].
needed;
265 total_score += _score_info[i].
score;
295 #ifdef ENABLE_NETWORK
305 FOR_ALL_COMPANIES(c) {
306 if (c->
index != old_owner) {
317 assert(old_owner != new_owner);
324 FOR_ALL_COMPANIES(c) {
325 for (i = 0; i < 4; i++) {
339 for (i = 0; i < 4; i++) {
360 FOR_ALL_SUBSIDIES(s) {
406 if (v->
Previous() == NULL)
delete v;
420 RemoveAllGroupsForCompany(old_owner);
424 if (g->
owner == old_owner) g->
owner = new_owner;
456 if (!v->ServiceIntervalIsCustom()) {
466 v->
owner = new_owner;
524 FOR_ALL_STATIONS(st) {
525 if (st->
owner == old_owner) {
535 if (wp->
owner == old_owner) {
548 if (g->
company == old_owner)
delete g;
555 FOR_ALL_STORY_PAGES(sp) {
556 if (sp->
company == old_owner)
delete sp;
600 SetDParam(0, STR_NEWS_COMPANY_IN_TROUBLE_TITLE);
601 SetDParam(1, STR_NEWS_COMPANY_IN_TROUBLE_DESCRIPTION);
603 AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, cni);
614 c->bankrupt_value = val;
619 assert(c->bankrupt_value > 0);
663 FOR_ALL_STATIONS(st) {
670 FOR_ALL_COMPANIES(c) {
692 FOR_ALL_COMPANIES(c) {
699 FOR_ALL_COMPANIES(c) {
767 for (
Price i = PR_BEGIN; i < PR_END; i++) {
772 switch (_price_base_specs[i].category) {
784 case 0: price *= 6;
break;
785 case 1: price *= 8;
break;
786 case 2: price *= 9;
break;
787 default: NOT_REACHED();
794 int shift = _price_base_multiplier[i] - 16 - 3;
807 price =
Clamp(_price_base_specs[i].start_price, -1, 1);
817 FOR_ALL_CARGOSPECS(cs) {
818 cs->current_payment = ((int64)cs->initial_payment * _economy.
inflation_payment) >> 16;
834 FOR_ALL_COMPANIES(c) {
862 static void HandleEconomyFluctuations()
869 _economy.
fluct = -12;
875 if (_economy.
fluct == 0) {
876 _economy.
fluct = -(int)
GB(Random(), 0, 2);
878 }
else if (_economy.
fluct == -12) {
879 _economy.
fluct =
GB(Random(), 0, 8) + 312;
890 memset(_price_base_multiplier, 0,
sizeof(_price_base_multiplier));
902 assert(price < PR_END);
927 void StartupEconomy()
932 _economy.
fluct =
GB(Random(), 0, 8) + 168;
961 if (index >= PR_END)
return 0;
963 Money cost = _price[index] * cost_factor;
975 Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days,
CargoID cargo_type)
985 uint32 var18 =
min(dist, 0xFFFF) | (
min(num_pieces, 0xFF) << 16) | (transit_days << 24);
988 int result =
GB(callback, 0, 14);
991 if (
HasBit(callback, 14)) result -= 0x4000;
996 return result * num_pieces * cs->current_payment / 8192;
1000 static const int MIN_TIME_FACTOR = 31;
1001 static const int MAX_TIME_FACTOR = 255;
1003 const int days1 = cs->transit_days[0];
1004 const int days2 = cs->transit_days[1];
1005 const int days_over_days1 =
max( transit_days - days1, 0);
1006 const int days_over_days2 =
max(days_over_days1 - days2, 0);
1018 const int time_factor =
max(MAX_TIME_FACTOR - days_over_days1 - days_over_days2, MIN_TIME_FACTOR);
1020 return BigMulS(dist * time_factor * num_pieces, cs->current_payment, 21);
1048 if (ind->
index == source)
continue;
1061 _cargo_delivery_destinations.
Include(ind);
1065 num_pieces -= amount;
1087 assert(num_pieces > 0);
1112 Money profit = GetTransportedGoodsIncome(accepted,
DistanceManhattan(source_tile, st->
xy), days_in_transit, cargo_type);
1120 case 0: profit += profit >> 1;
break;
1121 case 1: profit *= 2;
break;
1122 case 2: profit *= 3;
break;
1123 default: profit *= 4;
break;
1152 if (cargo_waiting == 0)
continue;
1171 current_station(front->last_station_visited)
1175 CargoPayment::~CargoPayment()
1189 SndPlayVehicleFx(SND_14_CASHTILL, this->
front);
1194 this->front->z_pos, this->visual_transfer, -this->visual_profit);
1197 this->front->z_pos, -this->visual_profit);
1200 cur_company.Restore();
1210 if (this->
owner == NULL) {
1230 Money profit = GetTransportedGoodsIncome(
1251 curr_station->loading_vehicles.push_back(front_v);
1269 for (
Vehicle *v = front_v; v != NULL; v = v->
Next()) {
1271 if (v->cargo_cap > 0 && v->cargo.TotalCount() > 0) {
1292 uint load_amount = e->info.load_amount;
1296 if (air_mail) load_amount =
CeilDiv(load_amount, 4);
1300 if (e->
GetGRF() != NULL && e->
GetGRF()->grf_version >= 8) {
1308 if (e->
GetGRF()->grf_version < 8) cb_load_amount =
GB(cb_load_amount, 0, 8);
1309 if (cb_load_amount >= 0x100) {
1311 }
else if (cb_load_amount != 0) {
1312 load_amount = cb_load_amount;
1321 return max(1u, load_amount);
1333 template<
class Taction>
1336 for (
Vehicle *w = v; w != NULL;
1338 if (!action(w))
return false;
1341 if (train->
IsMultiheaded() && !action(train->other_multiheaded_part))
return false;
1378 consist_capleft(consist_capleft), refit_mask(refit_mask) {}
1439 consist_capleft(consist_capleft), st(st), next_station(next_station), do_reserve(do_reserve) {}
1473 uint32 refit_mask = v->
GetEngine()->info.refit_mask;
1479 if (is_auto_refit) {
1483 FOR_EACH_SET_CARGO_ID(cid, refit_mask) {
1495 (consist_capleft[cid] == consist_capleft[new_cid] &&
1504 if (new_cid < NUM_CARGO && new_cid != v_start->cargo_type) {
1526 st(st), next_station(next_station) {}
1532 &v->
cargo, st->
xy, *next_station);
1555 assert(v->cargo_cap >= v->cargo.RemainingCount());
1560 if (!v->IsArticulatedPart() &&
1566 if (consist_capleft == NULL || v->cargo_cap == 0)
continue;
1567 (*consist_capleft)[v->cargo_type] += v->cargo_cap - v->cargo.RemainingCount();
1585 ticks += (overhang * ticks) / 8;
1624 int new_load_unload_ticks = 0;
1625 bool dirty_vehicle =
false;
1626 bool dirty_station =
false;
1628 bool completely_emptied =
true;
1629 bool anything_unloaded =
false;
1630 bool anything_loaded =
false;
1631 uint32 full_load_amount = 0;
1632 uint32 cargo_not_full = 0;
1633 uint32 cargo_full = 0;
1634 uint32 reservation_left = 0;
1640 uint artic_part = 0;
1641 for (
Vehicle *v = front; v != NULL; v = v->
Next()) {
1643 if (v->cargo_cap == 0)
continue;
1651 uint cargo_count = v->
cargo.UnloadCount();
1653 bool remaining =
false;
1655 assert(payment != NULL);
1666 if (v->cargo_cap < new_remaining) {
1668 v->cargo.Return(new_remaining - v->cargo_cap, &ge->
cargo, INVALID_STATION);
1679 anything_unloaded =
true;
1685 dirty_station =
true;
1695 amount_unloaded = v->cargo.Unload(amount_unloaded, &ge->
cargo, payment);
1696 remaining = v->cargo.UnloadCount() > 0;
1697 if (amount_unloaded > 0) {
1698 dirty_vehicle =
true;
1699 anything_unloaded =
true;
1700 new_load_unload_ticks += amount_unloaded;
1703 st->time_since_unload = 0;
1707 completely_emptied =
false;
1722 ge = &st->
goods[v->cargo_type];
1726 v->refit_cap = v->cargo_cap;
1730 switch (front->
type) {
1744 default: NOT_REACHED();
1752 assert(v->cargo_cap >= v->cargo.StoredCount());
1755 uint cap_left = v->cargo_cap - v->cargo.StoredCount();
1758 if (v->cargo.StoredCount() == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
1760 uint loaded = ge->
cargo.
Load(cap_left, &v->cargo, st->
xy, next_station);
1764 SetBit(reservation_left, v->cargo_type);
1768 if (loaded == cap_left) {
1769 SetBit(full_load_amount, v->cargo_type);
1771 ClrBit(full_load_amount, v->cargo_type);
1782 completely_emptied =
false;
1783 anything_loaded =
true;
1785 st->time_since_load = 0;
1786 st->last_vehicle_type = v->type;
1794 new_load_unload_ticks += loaded;
1796 dirty_vehicle = dirty_station =
true;
1800 if (v->cargo.StoredCount() >= v->cargo_cap) {
1801 SetBit(cargo_full, v->cargo_type);
1803 SetBit(cargo_not_full, v->cargo_type);
1807 if (anything_loaded || anything_unloaded) {
1815 completely_emptied &= anything_unloaded;
1817 if (!anything_unloaded)
delete payment;
1820 if (anything_loaded || anything_unloaded) {
1824 const uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
1826 new_load_unload_ticks = gradual_loading_wait_time[front->
type];
1838 bool finished_loading =
true;
1844 (cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) {
1845 finished_loading =
false;
1847 }
else if (cargo_not_full != 0) {
1848 finished_loading =
false;
1869 StringID percent_up_down = STR_NULL;
1878 if (completely_emptied) {
1881 dirty_vehicle =
true;
1882 TriggerVehicle(front, VEHICLE_TRIGGER_EMPTY);
1885 if (dirty_vehicle) {
1890 if (dirty_station) {
1905 if (st->loading_vehicles.empty())
return;
1908 std::list<Vehicle *>::iterator iter;
1911 for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
1927 if (last_loading == NULL)
return;
1929 for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
1932 if (v == last_loading)
break;
1936 const Industry *
const *isend = _cargo_delivery_destinations.
End();
1937 for (
Industry **iid = _cargo_delivery_destinations.
Begin(); iid != isend; iid++) {
1940 _cargo_delivery_destinations.
Clear();
1954 HandleEconomyFluctuations();
1957 static void DoAcquireCompany(
Company *c)
1964 SetDParam(0, STR_NEWS_COMPANY_MERGER_TITLE);
1965 SetDParam(1, c->bankrupt_value == 0 ? STR_NEWS_MERGER_TAKEOVER_TITLE : STR_NEWS_COMPANY_MERGER_DESCRIPTION);
1969 AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, cni);
1975 if (c->bankrupt_value == 0) {
1991 extern int GetAmountOwnedBy(
const Company *c,
Owner owner);
2019 if (!c->
is_ai)
return cost;
2034 c->bankrupt_value = 0;
2035 DoAcquireCompany(c);
2071 cost = -(cost - (cost >> 7));
2117 DoAcquireCompany(c);