Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Setting to scale cargo production of towns and industries #10606

Merged
merged 1 commit into from Jan 30, 2024

Conversation

2TallTyler
Copy link
Member

@2TallTyler 2TallTyler commented Apr 7, 2023

Motivation / Problem

In #11428 I present my solution to the old daylength patch which is so popular in JGR's Patchpack.

In my conversations with players, daylength actually has two common usecases:

  • Slowing down the rate of calendar and technology progression. This is handled by Feature: Setting for minutes per calendar year #11428.
  • Slowing down the economy, to enable less-dense and less-frequent networks, timetabling, and other "realistic" gameplay styles. This PR is my attempt to meet this need.

Slowing down economy time has several pieces:

  • Reducing industry cargo production
  • Reducing town cargo production
  • Slowing down vehicle running costs when trains are running empty, stabled in yards between runs, etc.
  • Slowing station rating loss from infrequent service

All of these are possible with NewGRFs. However, the last two are much easier with the Base Costs GRF and #11346.

Reducing town and industry production would require the player to fork the industry and house sets of their choice and make changes to the source code before recompiling. This is problematic with closed-source GRFs and abandoned GRFs that would need decompiling into uncommented NFO.

I think it's worth offering players this control in OpenTTD itself.

JGRPP has settings that do the same thing although it's applied on top of the daylength speed and the setting value is exponential so I have no idea how to interpret it). But the survey results indicate plenty of players tweaking production to suit their play styles:

Description

Adds two settings to scale the cargo production of:

  • Towns (including company HQ)
  • Industries

For houses, HQ, and basic industries, this simply scales the cargo by the selected percentage (using random to make up for rounding-to-zero losses).

Industries which use the "every 256 ticks" callback often do their own math with input cargos, and we don't want to break them by changing their output without their knowledge. We handle this by scaling the callback interval instead.

NewGRFs are unaware of the scale. They do not need to know about it, and giving them variables just gives authors footguns. Game Scripts can access settings directly so they don't need API additions.

The lower limit of cargo scaling for both industries and towns is 15%. This is a nicer number than the actual minimum (13%), which is determined by the 256-tick industry production callback. Any slower and the industry would not produce every month, leading to confusing feedback in the UI ("no production last month?"). Towns technically have no lower limit, but 15% is a nice limit where towns still produce any cargo. The actual minimum, 1%, typically has zero production even in large cities, which will confuse cargodist... So we make it 15% to match industries. 🙂

Limitations

  • Industries which use custom text to describe their cargo needs (FIRS, Industries of the Caribbean, etc) won't be accurate. I welcome ideas from NewGRF authors for how we can help them provide descriptive helptext.
  • Industries which produce passengers (Plaza as Industry, Apartment Blocks) are controlled by the Industry setting. Not out of laziness, but because this be argued either way so I chose the option with fewer edge cases. 😃
  • Houses have a cargo production callback called every 256 ticks, but since houses don't have input stockpiles, I don't bother scaling the callback interval and just scale the amount.
  • I did consider full economy scaling (including cargo value scaling), but that's more opinionated than letting players control cargo production individually without changing the rest of the economy.

Checklist for review

Some things are not automated, and forgotten often. This list is a reminder for the reviewers.

  • The bug fix is important enough to be backported? (label: 'backport requested')
  • This PR touches english.txt or translations? Check the guidelines
  • This PR affects the save game format? (label 'savegame upgrade')
  • This PR affects the GS/AI API? (label 'needs review: Script API')
    • ai_changelog.hpp, gs_changelog.hpp need updating.
    • The compatibility wrappers (compat_*.nut) need updating.
  • This PR affects the NewGRF API? (label 'needs review: NewGRF')

@2TallTyler 2TallTyler added preview This PR is receiving preview builds candidate: needs considering This Pull Request needs more opinions needs review: NewGRF Review requested from a NewGRF expert labels Apr 7, 2023
@DorpsGek DorpsGek temporarily deployed to preview-pr-10606 April 7, 2023 19:09 Inactive
@2TallTyler

This comment was marked as outdated.

@JGRennison

This comment was marked as outdated.

src/economy_func.h Outdated Show resolved Hide resolved
@DorpsGek DorpsGek temporarily deployed to preview-pr-10606 April 8, 2023 16:53 Inactive
@LC-Zorg
Copy link

LC-Zorg commented Apr 13, 2023

I like such changes so much... It's not controversial at all, they don't destroy anything, they don't impose anything, but they only give new possibilities. :)

I don't know how it will work in detail in combination with other sets, but in general I realy like this feature.
In my opinion, the percentage form is much more understandable than the one used in JGRPP. Maybe the only thing missing are separate settings for cities and industry. This can be good, for example, when you want to make a game based more on industry, or vice versa, on passenger transport. But a single setting isn't bad either.

src/industry_cmd.cpp Outdated Show resolved Hide resolved
src/newgrf.cpp Outdated Show resolved Hide resolved
src/object_cmd.cpp Outdated Show resolved Hide resolved
src/object_cmd.cpp Outdated Show resolved Hide resolved
src/table/settings/economy_settings.ini Outdated Show resolved Hide resolved
src/table/settings/economy_settings.ini Outdated Show resolved Hide resolved
src/town_cmd.cpp Outdated Show resolved Hide resolved
src/town_cmd.cpp Show resolved Hide resolved
src/settings_type.h Outdated Show resolved Hide resolved
@TrueBrain
Copy link
Member

I don't actually have an opinion about this PR. Code-wise it looks good and clean.

So I am curious what users will think of it. And best way to find out .. is to just merge it :) Curious if other developers have a (strong) opinion one way or the other :)

@DorpsGek DorpsGek temporarily deployed to preview-pr-10606 April 14, 2023 22:59 Inactive
Copy link
Member Author

@2TallTyler 2TallTyler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main question I have for users and other developers is whether we want one setting to scale all cargo, or one each for town cargo (including HQ production) and industry cargo. JGRPP has them separated, and it would be easy for me to split them. On the other hand...more settings. 🙂

src/table/settings/economy_settings.ini Outdated Show resolved Hide resolved
src/town_cmd.cpp Show resolved Hide resolved
@Andrew350
Copy link

The main question I have for users and other developers is whether we want one setting to scale all cargo, or one each for town cargo (including HQ production) and industry cargo. JGRPP has them separated, and it would be easy for me to split them. On the other hand...more settings. 🙂

Disclaimer: I am not a dev or even a player who is likely to ever use this feature.

With that said, I can guarantee you that if you don't allow people to scale each option separately you will inevitably be confronted with complaints about not allowing enough control for different playstyles. And while I generally agree about the stance on not adding new settings, this feature seems major enough to overlook that and give the (more vocal) playerbase the option to finetune their settings how they see fit. This is, after all, aimed more at said vocal playerbase than the general audience, so I say just go for it.

99% of players will never have a clue what these settings even mean anyways (just like the rest of the settings), so what's the harm in adding one more for the players who do understand it for such a (potential) major difference in gameplay? If it's not too complicated on your end (as you say it isn't), I suggest just making each option separate now - if nothing else just to avoid the headache of having to justify later why you didn't.

But that's just my 2 cents. 🙂

src/town_cmd.cpp Outdated Show resolved Hide resolved
@TrueBrain
Copy link
Member

The main question I have for users and other developers is whether we want one setting to scale all cargo, or one each for town cargo (including HQ production) and industry cargo. JGRPP has them separated, and it would be easy for me to split them. On the other hand...more settings. 🙂

I guess the question back is: what playstyles are possible / not possible with splitting them. Although I understand where @Andrew350 is coming from, and not even disagreeing, I don't fancy adding more settings because we are afraid people will complain :) I mean, clearly it is in JGRPP, so they can just use JGRPP instead. I would rather have we tailor the vanilla game to the 99%, and that we pick something that makes sense to them; not the vocal minority.

But again, I don't understand any of this (never bothered with economy in OpenTTD), so the question back is: what playstyle does it unlock :) And, to stay within the definition of vanilla's goal: can it be handled by NewGRFs instead?

@2TallTyler
Copy link
Member Author

Updated, fixed, rebased, etc., and I split town and industry scaling into two separate settings, since I agree that's a better choice for players — including me, probably.

But again, I don't understand any of this (never bothered with economy in OpenTTD), so the question back is: what playstyle does it unlock :) And, to stay within the definition of vanilla's goal: can it be handled by NewGRFs instead?

See the PR description for answers. 😄

@2TallTyler 2TallTyler added the preview This PR is receiving preview builds label Aug 3, 2023
@2TallTyler 2TallTyler temporarily deployed to preview August 3, 2023 11:29 — with GitHub Actions Inactive
@2TallTyler 2TallTyler temporarily deployed to preview October 1, 2023 18:49 — with GitHub Actions Inactive
src/industry_cmd.cpp Outdated Show resolved Hide resolved
src/newgrf.cpp Outdated Show resolved Hide resolved
src/newgrf.cpp Outdated

case 0x27: // industry cargo scale setting
*value = _settings_game.economy.industry_cargo_scale_percentage;
return true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should this be exposed to NewGRFs? We are 'going behind their back' to change adjust production, but then let them know anyway?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, hide it from NewGRF.
Also: settings should go into GetPatchVariable(). GetGlobalVariable() is for dynamic values.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an aside, putting it into GetPatchVariable would mean that you would not be able to modify the value of the settings during multiplayer games at all, because of the use of Action D.
There is otherwise no reason for the added settings to have the SF_NO_NETWORK flag.
Changing the value during a single-player game would result in it not being visible to GRFs until the next save/load or GRF reload.
This would not be ideal, given that it's quite typical that you'll want to adjust the scaling as the game develops (usually, reduce it further as the network size increases).

If these variables were exposed to GRFs, GetGlobalVariable would be more useful than GetPatchVariable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to not expose it to GRF. The original intention was to allow industry sets like FIRS to provide accurate helptext, but I agree that the potential for misuse might outweigh this.

src/settings_type.h Outdated Show resolved Hide resolved
src/table/settings/economy_settings.ini Outdated Show resolved Hide resolved
src/town_cmd.cpp Show resolved Hide resolved
src/town_cmd.cpp Outdated Show resolved Hide resolved
src/town_cmd.cpp Outdated Show resolved Hide resolved
src/industry_cmd.cpp Outdated Show resolved Hide resolved
src/industry_cmd.cpp Show resolved Hide resolved
@PeterN
Copy link
Member

PeterN commented Oct 2, 2023

Does this distinguish between primary and secondary industries?

If output of primary industries is reduced, then logically input of secondary industries is reduced, so already their output will lower, and then it is reduced further?

(And then tertiary...)

@2TallTyler
Copy link
Member Author

Yes. The modified scale-the-amount code only affects primary industry production, while secondary industries are not affected. NewGRF industries like ECS or Industries of the Caribbean that use stockpiling and the every-256-ticks callback produce less often, so it takes them longer to work through the stockpile. As the designer of one of these (Caribbean), that is how I would intend it to work, since the production rate is balanced against primary industry production.

Also, as @JGRennison mentioned on Discord, a similar implementation (I started with cherry-picking that commit) has been in JGRPP for several years. There, it's used to counteract the effects of daylength, typically turned up to compensate for everything else running more slowly. 😃

@PeterN
Copy link
Member

PeterN commented Oct 2, 2023

Yes. The modified scale-the-amount code only affects primary industry production,

Okay... because the section where secondary production occurs is elsewhere and not touched by this change. Makes sense.

Also, as @JGRennison mentioned on Discord, a similar implementation (I started with cherry-picking that commit) has been in JGRPP for several years. There, it's used to counteract the effects of daylength, typically turned up to compensate for everything else running more slowly. 😃

Lovely, but experience of a change in another build that many of us have not used doesn't mean much when it comes to code reviews.

@2TallTyler
Copy link
Member Author

Lovely, but experience of a change in another build that many of us have not used doesn't mean much when it comes to code reviews.

Oh, agreed. I don't say that as a "gotcha," but I figured it was worth noting in case anyone wanted to see how it works over there. 🙂

@2TallTyler 2TallTyler added this to the 14.0 milestone Nov 3, 2023
@2TallTyler
Copy link
Member Author

@nielsmh As we discussed on Discord, I'll be changing the control of calendar progress speed in #11428 to "minutes per game year" units. What are your thoughts on the units for this pair of settings? Make them match calendar speed somehow, or keep them as percentages?

(Bear in mind that industry production cannot be slower than about 13% of vanilla, or some months will have no production with a callback-based industry set, leading to all sorts of usability problems. This could be fixed with averaging or something, but that's probably out of scope for now...)

@nielsmh
Copy link
Contributor

nielsmh commented Nov 27, 2023

I think actually entering minutes for direct entry and up-down buttons makes the most sense. However, the setting itself should ideally be displayed with a unit conversion too:

  • Minutes per calendar year: 12 minutes (standard game speed)
  • Minutes per calendar year: 6 minutes (speed-up, 200% game speed)
  • Minutes per calendar year: 60 minutes (slow-down, 20% game speed)
  • Minutes per calendar year: 1,440 minutes (slow-down, 0.83% game speed)

The last one is perhaps a bit extreme, but ideally I think printing a percentage with two significant digits, even if those need to be decimal, is preferable.

As for production scaling, can it perhaps be done in the same way? "Minutes per production year"?

@2TallTyler

This comment was marked as outdated.

src/economy_func.h Outdated Show resolved Hide resolved
@michicc
Copy link
Member

michicc commented Jan 30, 2024

I'm not familiar with the JGR implementation, are there any additions a NewGRF could query (like some global Act D or Act 2 variable)?

I have no idea if any NewGRF does this, but in theory they could read back the produced cargo, which with this scaling is not what the NewGRF might expect. Very theoretically I guess, I'm just wondering if this scaling factor is something that a NewGRF should be able to read.

Eh, already answered. Better eyesight needed :)

@JGRennison
Copy link
Contributor

I'm not familiar with the JGR implementation, are there any additions a NewGRF could query (like some global Act D or Act 2 variable)?

I have no idea if any NewGRF does this, but in theory they could read back the produced cargo, which with this scaling is not what the NewGRF might expect. Very theoretically I guess, I'm just wondering if this scaling factor is something that a NewGRF should be able to read.

In the implementation in my branch, there are deliberately not any such variables. The scaling is intended to be as transparent as practical from the point of view of the GRF. This is to make it more likely that the scaling works correctly, and as a secondary factor, to discourage GRF attempts to undo it or apply the scaling a second time, or to refuse to work if scaling is detected.

Past month production/transported values are used by GRFs such as BSPI for stockpiling mechanics. The actual values are what is presented back to the GRF.
For example, in the case of BSPI a higher production rate leads to the stockpile being depleted faster, due to the higher rate at which cargo is transported, which is a reasonable mechanic.

Copy link
Member

@michicc michicc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plague

@2TallTyler 2TallTyler merged commit 41f2eed into OpenTTD:master Jan 30, 2024
20 checks passed
@2TallTyler 2TallTyler deleted the economy-scale branch January 30, 2024 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
candidate: needs considering This Pull Request needs more opinions needs review: NewGRF Review requested from a NewGRF expert preview This PR is receiving preview builds
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet