Better late than never though.
Anyway, by using the built-in functions I can determine quite easily how many passengers, mail, goods are delivered to a town. Same with food/water since TTD tracks that. Idem for any custom cargo with the correct flags set. (So ECS Tourists are treated as passengers and so on)
Toys, coal, and valuables are a different matter though.
Trying to think of a way I thought to loop through all industries on the map once per month, adding the 'cargo in storage' amount to the custom data field in the custom town object responsible for keeping track of that kind of cargo. I.e. when it finds a power plant it looks at the amount of coal delivered to it so far on the last day of the month. That gets added to town.cargo_supplied[6] or somesuch. There are a number of problems with this approach though.
1: It doesn't work.
Either the town's 'influence area' isn't what I think it is (any square with local authority: <TOWNNAME>), or an industry's location isn't what I think it is(the square I click on when the fund button is pressed) (these two are unlikely to be true), or the game does somehow not keep track of the data I want in the way I think it does, or seems at least clear from the API.
On my setup, the Log.Info is never called, if I put an if() around it for a specific town and build an industry in that town!
Code: Select all
local inds = GSIndustryList();
local loc = null;
foreach(i, _ in inds)
{
loc = GSIndustry.GetLocation(i);
foreach(t, _ in this.towns)
{
if(GSTown.IsWithinTownInfluence((this.towns[t]).id, loc) == true)
{
Log.Info("Industry found in town with this much coal: "+GSIndustry.GetStockpiledCargo(i, COAL),Log.LVL_INFO);
if(GSIndustry.IsCargoAccepted(i, COAL) == GSIndustry.CAS_ACCEPTED && GSIndustry.GetStockpiledCargo(i, COAL) >= 0)
{(this.towns[t]).AddAdvancedCargo(GSIndustry.GetStockpiledCargo(i, COAL),0,0);}
if(GSIndustry.IsCargoAccepted(i, TOYS) == GSIndustry.CAS_ACCEPTED && GSGame.GetLandscape() == GSGame.LT_TOYLAND && GSIndustry.GetStockpiledCargo(i, TOYS) >= 0)
{(this.towns[t]).AddAdvancedCargo(0,GSIndustry.GetStockpiledCargo(i, TOYS),0);}
if(GSIndustry.IsCargoAccepted(i, VALUABLES) == GSIndustry.CAS_ACCEPTED && GSGame.GetLandscape() != GSGame.LT_TOYLAND && GSIndustry.GetStockpiledCargo(i, VALUABLES) >= 0)
{(this.towns[t]).AddAdvancedCargo(0,0,GSIndustry.GetStockpiledCargo(i, VALUABLES));}
}
}
}
2: Cargo delivered on the last day of the month may or may not count towards the goal.
- This is annoying to say the least.
3: It's needlessly long. The algorithm takes O(n^2) operations, where n is the number of towns/industries, iff GetStockpiledCargo is constant. If that's instead f(n), then it's O(f(n)n^2) ops. (I know addadvancedcargo IS constant-time).
Ideally I would want to replace this section of code with something equivalent that's faster and takes into account the last day. Something like having the functions int32 GSIndustry.GetDeliveredCargo(industry_id, cargotype) and TownID GSIndustry.GetLocalAuthority(industry_id).
The former function simply gets the amount of <whatever good> is delivered to the industry last month, and the latter gets me in which town the industry is. It'd return -1 or NULL if it failed ofc.
With these two functions one could make it far easier, you would just need to keep a conversion table between town id's and in which places these are in my array inside this function. Seems okay enough.
One more question,a little simpler: In C++ I can do this:
Code: Select all
class f{
static int k;
inline int thefunction(int g){return g + k;}
}
f::k = GetSetting();
What would be the script equivalent?
And now the final question:
At the beginning of each month, I use a trick to grow the town. I set the 'grow every X days' to some grotesque number, like X = 999,999. And then use GSTown.ExpandTown(TownID id, int32 amt) to grow it. Mostly because I'm using some mathematics to figure out how much I want a town to grow depending on cargo input. At least those work perfectly

The question is: How do I SHRINK a town?
E.g. I want to remove n randomly determined houses from it, where n is an integer,via gamescript.
This is important to prevent people that will stockpile goods to get a town (temporarily) bigger than their normal network would allow it to be.