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;
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;
1650 uint cargo_count = v->
cargo.UnloadCount();
1652 bool remaining =
false;
1664 if (v->cargo_cap < new_remaining) {
1666 v->cargo.Return(new_remaining - v->cargo_cap, &ge->
cargo, INVALID_STATION);
1677 anything_unloaded =
true;
1683 dirty_station =
true;
1693 amount_unloaded = v->cargo.Unload(amount_unloaded, &ge->
cargo, payment);
1694 remaining = v->cargo.UnloadCount() > 0;
1695 if (amount_unloaded > 0) {
1696 dirty_vehicle =
true;
1697 anything_unloaded =
true;
1698 new_load_unload_ticks += amount_unloaded;
1701 st->time_since_unload = 0;
1705 completely_emptied =
false;
1720 ge = &st->
goods[v->cargo_type];
1724 v->refit_cap = v->cargo_cap;
1728 switch (front->
type) {
1742 default: NOT_REACHED();
1750 assert(v->cargo_cap >= v->cargo.StoredCount());
1753 uint cap_left = v->cargo_cap - v->cargo.StoredCount();
1756 if (v->cargo.StoredCount() == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
1758 uint loaded = ge->
cargo.
Load(cap_left, &v->cargo, st->
xy, next_station);
1762 SetBit(reservation_left, v->cargo_type);
1766 if (loaded == cap_left) {
1767 SetBit(full_load_amount, v->cargo_type);
1769 ClrBit(full_load_amount, v->cargo_type);
1780 completely_emptied =
false;
1781 anything_loaded =
true;
1783 st->time_since_load = 0;
1784 st->last_vehicle_type = v->type;
1792 new_load_unload_ticks += loaded;
1794 dirty_vehicle = dirty_station =
true;
1798 if (v->cargo.StoredCount() >= v->cargo_cap) {
1799 SetBit(cargo_full, v->cargo_type);
1801 SetBit(cargo_not_full, v->cargo_type);
1805 if (anything_loaded || anything_unloaded) {
1813 completely_emptied &= anything_unloaded;
1815 if (!anything_unloaded)
delete payment;
1818 if (anything_loaded || anything_unloaded) {
1822 const uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
1824 new_load_unload_ticks = gradual_loading_wait_time[front->
type];
1836 bool finished_loading =
true;
1842 (cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) {
1843 finished_loading =
false;
1845 }
else if (cargo_not_full != 0) {
1846 finished_loading =
false;
1867 StringID percent_up_down = STR_NULL;
1876 if (completely_emptied) {
1879 dirty_vehicle =
true;
1880 TriggerVehicle(front, VEHICLE_TRIGGER_EMPTY);
1883 if (dirty_vehicle) {
1888 if (dirty_station) {
1903 if (st->loading_vehicles.empty())
return;
1906 std::list<Vehicle *>::iterator iter;
1909 for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
1925 if (last_loading == NULL)
return;
1927 for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
1930 if (v == last_loading)
break;
1934 const Industry *
const *isend = _cargo_delivery_destinations.
End();
1935 for (
Industry **iid = _cargo_delivery_destinations.
Begin(); iid != isend; iid++) {
1938 _cargo_delivery_destinations.
Clear();
1952 HandleEconomyFluctuations();
1955 static void DoAcquireCompany(
Company *c)
1962 SetDParam(0, STR_NEWS_COMPANY_MERGER_TITLE);
1963 SetDParam(1, c->bankrupt_value == 0 ? STR_NEWS_MERGER_TAKEOVER_TITLE : STR_NEWS_COMPANY_MERGER_DESCRIPTION);
1967 AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, cni);
1973 if (c->bankrupt_value == 0) {
1989 extern int GetAmountOwnedBy(
const Company *c,
Owner owner);
2017 if (!c->
is_ai)
return cost;
2032 c->bankrupt_value = 0;
2033 DoAcquireCompany(c);
2069 cost = -(cost - (cost >> 7));
2115 DoAcquireCompany(c);