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);
659 FOR_ALL_COMPANIES(c) {
667 FOR_ALL_STATIONS(st) {
674 FOR_ALL_COMPANIES(c) {
698 FOR_ALL_COMPANIES(c) {
766 for (
Price i = PR_BEGIN; i < PR_END; i++) {
771 switch (_price_base_specs[i].category) {
783 case 0: price *= 6;
break;
784 case 1: price *= 8;
break;
785 case 2: price *= 9;
break;
786 default: NOT_REACHED();
793 int shift = _price_base_multiplier[i] - 16 - 3;
806 price =
Clamp(_price_base_specs[i].start_price, -1, 1);
816 FOR_ALL_CARGOSPECS(cs) {
817 cs->current_payment = ((int64)cs->initial_payment * _economy.
inflation_payment) >> 16;
833 FOR_ALL_COMPANIES(c) {
861 static void HandleEconomyFluctuations()
868 _economy.
fluct = -12;
874 if (_economy.
fluct == 0) {
875 _economy.
fluct = -(int)
GB(Random(), 0, 2);
877 }
else if (_economy.
fluct == -12) {
878 _economy.
fluct =
GB(Random(), 0, 8) + 312;
889 memset(_price_base_multiplier, 0,
sizeof(_price_base_multiplier));
901 assert(price < PR_END);
926 void StartupEconomy()
931 _economy.
fluct =
GB(Random(), 0, 8) + 168;
960 if (index >= PR_END)
return 0;
962 Money cost = _price[index] * cost_factor;
974 Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days,
CargoID cargo_type)
984 uint32 var18 =
min(dist, 0xFFFF) | (
min(num_pieces, 0xFF) << 16) | (transit_days << 24);
987 int result =
GB(callback, 0, 14);
990 if (
HasBit(callback, 14)) result -= 0x4000;
995 return result * num_pieces * cs->current_payment / 8192;
999 static const int MIN_TIME_FACTOR = 31;
1000 static const int MAX_TIME_FACTOR = 255;
1002 const int days1 = cs->transit_days[0];
1003 const int days2 = cs->transit_days[1];
1004 const int days_over_days1 =
max( transit_days - days1, 0);
1005 const int days_over_days2 =
max(days_over_days1 - days2, 0);
1017 const int time_factor =
max(MAX_TIME_FACTOR - days_over_days1 - days_over_days2, MIN_TIME_FACTOR);
1019 return BigMulS(dist * time_factor * num_pieces, cs->current_payment, 21);
1047 if (ind->
index == source)
continue;
1060 _cargo_delivery_destinations.
Include(ind);
1064 num_pieces -= amount;
1086 assert(num_pieces > 0);
1111 Money profit = GetTransportedGoodsIncome(accepted,
DistanceManhattan(source_tile, st->
xy), days_in_transit, cargo_type);
1119 case 0: profit += profit >> 1;
break;
1120 case 1: profit *= 2;
break;
1121 case 2: profit *= 3;
break;
1122 default: profit *= 4;
break;
1151 if (cargo_waiting == 0)
continue;
1170 current_station(front->last_station_visited)
1174 CargoPayment::~CargoPayment()
1188 SndPlayVehicleFx(SND_14_CASHTILL, this->
front);
1193 this->front->z_pos, this->visual_transfer, -this->visual_profit);
1196 this->front->z_pos, -this->visual_profit);
1199 cur_company.Restore();
1209 if (this->
owner == NULL) {
1229 Money profit = GetTransportedGoodsIncome(
1250 curr_station->loading_vehicles.push_back(front_v);
1268 for (
Vehicle *v = front_v; v != NULL; v = v->
Next()) {
1270 if (v->cargo_cap > 0 && v->cargo.TotalCount() > 0) {
1291 uint load_amount = e->info.load_amount;
1295 if (air_mail) load_amount =
CeilDiv(load_amount, 4);
1299 if (e->
GetGRF() != NULL && e->
GetGRF()->grf_version >= 8) {
1307 if (e->
GetGRF()->grf_version < 8) cb_load_amount =
GB(cb_load_amount, 0, 8);
1308 if (cb_load_amount >= 0x100) {
1310 }
else if (cb_load_amount != 0) {
1311 load_amount = cb_load_amount;
1320 return max(1u, load_amount);
1332 template<
class Taction>
1335 for (
Vehicle *w = v; w != NULL;
1337 if (!action(w))
return false;
1340 if (train->
IsMultiheaded() && !action(train->other_multiheaded_part))
return false;
1377 consist_capleft(consist_capleft), refit_mask(refit_mask) {}
1438 consist_capleft(consist_capleft), st(st), next_station(next_station), do_reserve(do_reserve) {}
1472 uint32 refit_mask = v->
GetEngine()->info.refit_mask;
1478 if (is_auto_refit) {
1482 FOR_EACH_SET_CARGO_ID(cid, refit_mask) {
1494 (consist_capleft[cid] == consist_capleft[new_cid] &&
1503 if (new_cid < NUM_CARGO && new_cid != v_start->cargo_type) {
1525 st(st), next_station(next_station) {}
1531 &v->
cargo, st->
xy, *next_station);
1554 assert(v->cargo_cap >= v->cargo.RemainingCount());
1559 if (!v->IsArticulatedPart() &&
1565 if (consist_capleft == NULL || v->cargo_cap == 0)
continue;
1566 (*consist_capleft)[v->cargo_type] += v->cargo_cap - v->cargo.RemainingCount();
1584 ticks += (overhang * ticks) / 8;
1623 int new_load_unload_ticks = 0;
1624 bool dirty_vehicle =
false;
1625 bool dirty_station =
false;
1627 bool completely_emptied =
true;
1628 bool anything_unloaded =
false;
1629 bool anything_loaded =
false;
1630 uint32 full_load_amount = 0;
1631 uint32 cargo_not_full = 0;
1632 uint32 cargo_full = 0;
1633 uint32 reservation_left = 0;
1639 uint artic_part = 0;
1640 for (
Vehicle *v = front; v != NULL; v = v->
Next()) {
1642 if (v->cargo_cap == 0)
continue;
1648 uint cargo_count = v->
cargo.UnloadCount();
1650 bool remaining =
false;
1652 assert(payment != NULL);
1663 if (v->cargo_cap < new_remaining) {
1665 v->cargo.Return(new_remaining - v->cargo_cap, &ge->
cargo, INVALID_STATION);
1676 anything_unloaded =
true;
1682 dirty_station =
true;
1692 amount_unloaded = v->cargo.Unload(amount_unloaded, &ge->
cargo, payment);
1693 remaining = v->cargo.UnloadCount() > 0;
1694 if (amount_unloaded > 0) {
1695 dirty_vehicle =
true;
1696 anything_unloaded =
true;
1697 new_load_unload_ticks += amount_unloaded;
1700 st->time_since_unload = 0;
1704 completely_emptied =
false;
1719 ge = &st->
goods[v->cargo_type];
1723 v->refit_cap = v->cargo_cap;
1727 switch (front->
type) {
1741 default: NOT_REACHED();
1749 assert(v->cargo_cap >= v->cargo.StoredCount());
1752 uint cap_left = v->cargo_cap - v->cargo.StoredCount();
1754 if (v->cargo.StoredCount() == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
1757 uint loaded = ge->
cargo.
Load(cap_left, &v->cargo, st->
xy, next_station);
1761 SetBit(reservation_left, v->cargo_type);
1765 if (loaded == cap_left) {
1766 SetBit(full_load_amount, v->cargo_type);
1768 ClrBit(full_load_amount, v->cargo_type);
1779 completely_emptied =
false;
1780 anything_loaded =
true;
1782 st->time_since_load = 0;
1783 st->last_vehicle_type = v->type;
1791 new_load_unload_ticks += loaded;
1793 dirty_vehicle = dirty_station =
true;
1797 if (v->cargo.StoredCount() >= v->cargo_cap) {
1798 SetBit(cargo_full, v->cargo_type);
1800 SetBit(cargo_not_full, v->cargo_type);
1804 if (anything_loaded || anything_unloaded) {
1812 completely_emptied &= anything_unloaded;
1814 if (!anything_unloaded)
delete payment;
1817 if (anything_loaded || anything_unloaded) {
1821 const uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
1823 new_load_unload_ticks = gradual_loading_wait_time[front->
type];
1835 bool finished_loading =
true;
1841 (cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) {
1842 finished_loading =
false;
1844 }
else if (cargo_not_full != 0) {
1845 finished_loading =
false;
1866 StringID percent_up_down = STR_NULL;
1875 if (completely_emptied) {
1878 dirty_vehicle =
true;
1879 TriggerVehicle(front, VEHICLE_TRIGGER_EMPTY);
1882 if (dirty_vehicle) {
1887 if (dirty_station) {
1902 if (st->loading_vehicles.empty())
return;
1905 std::list<Vehicle *>::iterator iter;
1908 for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
1924 if (last_loading == NULL)
return;
1926 for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
1929 if (v == last_loading)
break;
1933 const Industry *
const *isend = _cargo_delivery_destinations.
End();
1934 for (
Industry **iid = _cargo_delivery_destinations.
Begin(); iid != isend; iid++) {
1937 _cargo_delivery_destinations.
Clear();
1951 HandleEconomyFluctuations();
1954 static void DoAcquireCompany(
Company *c)
1961 SetDParam(0, STR_NEWS_COMPANY_MERGER_TITLE);
1962 SetDParam(1, c->bankrupt_value == 0 ? STR_NEWS_MERGER_TAKEOVER_TITLE : STR_NEWS_COMPANY_MERGER_DESCRIPTION);
1966 AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, cni);
1972 if (c->bankrupt_value == 0) {
1988 extern int GetAmountOwnedBy(
const Company *c,
Owner owner);
2016 if (!c->
is_ai)
return cost;
2031 c->bankrupt_value = 0;
2032 DoAcquireCompany(c);
2068 cost = -(cost - (cost >> 7));
2114 DoAcquireCompany(c);