robiz wrote: ↑30 Aug 2021 18:37
If I've correctly investigated the game, I've found some missing materials.
Hey robiz. I checked it and you are right, there are missing cargos, because the first 12 cargo types are the same as basic tropical economy, so that it was used instead of generated categories. In the OpenTTD 12.0, there is a way for the GS to get the list of active newGRFs, which would solve this issue. But this could be done with a hotfix.
abloke wrote: ↑31 Aug 2021 02:26
Does within range mean just a tile owned by the local authority (as I understand it every tile in the map is owned by some town, even ones very far away from the town, which is why making airports with the noise limit on can be a pain) or does it just mean within the zone you can see by going to Local Authority -> View Zone?
Does the industry have to be within the range or does it just have to be the station accepting the given cargo that's within the zone?
Hey abloke. The best way to find out if it is fine is to put down a station and if the station has the same name as the town, it will be counted towards that town. So you can have a hub quite far from the town based on the nearby towns areas. If you plan to fund an industry, it is also good to test the spots with a few stations. This way you can also find the edges of the catchment area and put it as far as possible. I would try to keep the industry and station with the same name, it might work with different names, but you cant be sure. I dont know the exact rules how it works, it is only a GS function that I call.
abloke wrote: ↑31 Aug 2021 02:26
Why does population sometimes decrease even when a town shows 'growing within ~300 days' or similar? It seems to dip down then come back up a lot.
The regular town growing rules apply. A house can be demolished, rebuilt, added or a road can be added. A fountain can be built instead of a big house reducing the population.
abloke wrote: ↑31 Aug 2021 02:26
Perhaps a better explanation on how industry descending and ascending sort things into tiers would be helpful and maybe a look at making sure the highest tier (cat II in descending, cat IV in ascending) is definitely end products also.
The industry randomization is proceduraly generated, there are no economy templates, so anything can happen. It is meant to reduce the number of different industries you need per town and to incentivize providing all cargo types to those industries. As you know FIRS industries increase production when all cargos are provided, so it makes most sense to use it there. Here is exactly how the categories are generated:
1. Create 5 lists of industries: raw, 1 cargo accepting, 2, 3, and more or equal to 4. The passangers and mails are ignored here.
2. From these lists, the individual categories are created.
3. Cat I. PASS and MAIL
4. Cat II. Pick one of the 1 cargo accepting industries. If there is none, pick from raw industries. This should produce 1 cargo, mostly 2 (from raw industry like farm)
5. Cat III. Pick one of the 2 cargo accepting industries if there are more than 2 (enought variance) or there are not enough 1 cargo and raw industries to form this category. Otherwise form the category from 1 cargo and raw industries. This should produce 2 cargos, at most 3 (again raw industry).
6. Cat IV. Same as Cat III, but uses 3 cargo industries with fallback to 2 cargo industries + 1 cargo industries / raw industries.
7. Cat V. Same as Cat III, but uses 4+ cargo industries with fallback to 3 cargo industries + 1 cargo industries / raw industries. This category can be not created if there are not enought industries, so it is a possibility of only 4 categories.
8. If descending, swap the order of categories.
9. Profit by failing to create sensible categories for most of the economies (and sometimes fail completely).
Below is the code if you want to peek into it. As you can see, there is no way of specifying luxury cargos. For that purpose, there are the other randomization options, which have hand picked categories.
- [+] Spoiler
-
Code: Select all
local industry_type_list = GSIndustryTypeList();
local list_raw = [];
local list_1 = [];
local list_2 = [];
local list_3 = [];
local list_4 = [];
foreach (industry, _ in industry_type_list) {
local cargo_list = GSIndustryType.GetAcceptedCargo(industry);
cargo_list.RemoveItem(0); // exclude PASS
cargo_list.RemoveItem(2); // exclude MAIL
switch (cargo_list.Count())
{
case 0:
break;
case 1:
if (GSIndustryType.IsRawIndustry(industry))
list_raw.append(industry);
else
list_1.append(industry);
break;
case 2:
if (GSIndustryType.IsRawIndustry(industry))
list_raw.append(industry);
else
list_2.append(industry);
break;
case 3:
list_3.append(industry);
break;
default:
list_4.append(industry);
}
}
// 1. Category (PASS, MAIL)
// 2. Category
{
if (list_1.len() == 0) {
local rand = GSBase.RandRange(list_raw.len());
categories.append([list_raw[rand]]);
list_raw.remove(rand);
}
else {
local rand = GSBase.RandRange(list_1.len());
categories.append([list_1[rand]]);
list_1.remove(rand);
}
}
// 3. Category
if (list_2.len() > 2 || (list_1.len() < 2 && list_2.len() > 0)) {
local rand = GSBase.RandRange(list_2.len());
categories.append([list_2[rand]]);
list_2.remove(rand);
}
else {
local rand = GSBase.RandRange(3);
if (rand < list_2.len()) {
categories.append([list_2[rand]]);
list_2.remove(rand);
}
else {
if (list_raw.len() > 0) {
local rand_1 = GSBase.RandRange(list_1.len());
local rand_raw = GSBase.RandRange(list_raw.len());
categories.append([list_1[rand_1], list_raw[rand_raw]]);
list_1.remove(rand_1);
list_raw.remove(rand_raw);
}
else {
local rand_1 = GSBase.RandRange(list_1.len());
local rand_2 = GSBase.RandRange(list_1.len() - 1);
categories.append([list_1[rand_1], list_1[rand_2 >= rand_1 ? rand_2 + 1 : rand_2]]);
list_1.remove(rand_1);
list_1.remove(rand_2);
}
}
}
// 4. Category
if (list_3.len() > 2 || ((list_2.len() == 0 || (list_1.len() + list_raw.len() == 0)) && list_3.len() > 0)) {
local rand = GSBase.RandRange(list_3.len());
categories.append([list_3[rand]]);
list_3.remove(rand);
}
else {
local rand = GSBase.RandRange(3);
if (rand < list_3.len()) {
categories.append([list_3[rand]]);
list_3.remove(rand);
}
else {
local list = clone list_1;
list.extend(list_raw);
local rand_1 = GSBase.RandRange(list.len());
local rand_2 = GSBase.RandRange(list_2.len());
categories.append([list[rand_1], list_2[rand_2]]);
if (rand_1 < list_1.len())
list_1.remove(rand_1);
else
list_raw.remove(rand_1 - list_1.len());
list_2.remove(rand_2);
}
}
// 5. Category
if (list_4.len() > 2 || ((list_3.len() < 5 || (list_1.len() + list_raw.len() < 5)) && list_4.len() > 0)) {
local rand = GSBase.RandRange(list_4.len());
categories.append([list_4[rand]]);
list_4.remove(rand);
}
else if (list_4.len() > 0) {
local rand = GSBase.RandRange(3);
if (rand < list_4.len()) {
categories.append([list_4[rand]]);
list_4.remove(rand);
}
else {
local list = clone list_1;
list.extend(list_raw);
local rand_1 = GSBase.RandRange(list.len());
local rand_3 = GSBase.RandRange(list_3.len());
categories.append([list[rand_1], list_3[rand_3]]);
if (rand_1 < list_1.len())
list_1.remove(rand_1);
else
list_raw.remove(rand_1 - list_1.len());
list_3.remove(rand_3);
}
}
else if (list_3.len() > 4 && (list_1.len() + list_raw.len() > 4)) {
local list = clone list_1;
list.extend(list_raw);
local rand_1 = GSBase.RandRange(list.len());
local rand_3 = GSBase.RandRange(list_3.len());
categories.append([list[rand_1], list_3[rand_3]]);
if (rand_1 < list_1.len())
list_1.remove(rand_1);
else
list_raw.remove(rand_1 - list_1.len());
list_3.remove(rand_3);
}
if (!ascending) {
local category_reverse = [];
for (local i = categories.len() - 1; i >= 0; --i) {
category_reverse.append(categories[i]);
}
return category_reverse;
}