Compare commits

..
303 Commits
Author SHA1 Message Date
Tyler TrahanandGitHub c56e08d5c3 Doc: Update changelog for 16.0-beta3 (redux) (#16014) 2026-09-19 08:54:49 -04:00
translators e309ba1756 Update: Translations from eints
hebrew: 58 changes by zetametroid
french: 51 changes by glx22
2026-09-19 08:58:01 +00:00
Tyler TrahanandGitHub 2692444f42 Change: Lowering tiles when terraforming makes rocky slopes (#15822) 2026-09-18 18:57:54 -04:00
Tyler TrahanandGitHub 5b513abef0 Add: Show train length in reworked vehicle info panel (#15389) 2026-09-18 14:47:06 -04:00
de90358094 Change: Allow road vehicles to overtake through junctions between one-way roads (#15445)
Co-authored-by: Tyler Trahan <tyler@tylertrahan.com>
2026-09-18 14:45:50 -04:00
Peter NelsonandGitHub f58eac1d3a Fix #15824: Game crash when truncating cargo of crashed vehicle (#16005) 2026-09-18 19:33:03 +01:00
Rubidiumandrubidium42 ec444f7315 Codechange: remove out-of-date comments about the old custom difficulty 2026-09-17 18:08:58 +02:00
Rubidiumandrubidium42 b2da5d7ef9 Codechange: replace transitional helper operator| with direct constructor 2026-09-17 17:31:09 +02:00
Peter NelsonandGitHub 1aca0b60a8 Doc: Update changelog for 16.0-beta3 (#16003) 2026-09-15 23:06:51 +01:00
Rubidiumandrubidium42 1e83380df9 Codechange: migrate settings to use SaveLoad function calls 2026-09-15 20:57:48 +02:00
Rubidiumandrubidium42 a3f657f4f4 Codechange: replace SLE(G)_(COND)VAR(NAME) with function call 2026-09-15 20:57:48 +02:00
Rubidiumandrubidium42 b33be554e2 Codechange: replace SLE(G)_(COND)SSTR(NAME) with function call
By doing so the standard EnumMask construction method can be used,
instead of VarType's | operator hack. This removes that hack.
2026-09-15 20:57:48 +02:00
Rubidiumandrubidium42 704eea81ee Codechange: replace SLE(G)_(COND)REF with function call
The new includes are needed as the reference variables are checked for being
actual pool type elements, which requires more than a forward declaration.
2026-09-15 20:57:48 +02:00
Rubidiumandrubidium42 b2bf655714 Codechange: replace SLE(G)_(COND)ARR(NAME) with function call 2026-09-15 20:57:48 +02:00
Rubidiumandrubidium42 3e5d093336 Codechange: replace SLE(G)_(COND)VECTOR with function call 2026-09-15 20:57:48 +02:00
Rubidiumandrubidium42 02eb06ccd4 Codechange: replace SLE(G)_(COND)REFLIST with function call 2026-09-15 20:57:48 +02:00
Rubidiumandrubidium42 01377cbfd4 Codechange: replace SLE_(COND)REFVECTOR with function call 2026-09-15 20:57:48 +02:00
Rubidiumandrubidium42 7de9eb4c2f Codechange: replace SLE_SAVEBYTE with function call 2026-09-15 20:57:48 +02:00
Rubidiumandrubidium42 ae1067023c Codechange: replace SLEG_(COND)STRUCT and SLEG_(COND)STRUCTLIST with function call 2026-09-15 20:57:48 +02:00
Rubidiumandrubidium42 fd0f4f95a4 Codechange: add SaveLoad helper functions to construct SaveLoad objects
These helper functions determine the memory type given the actual C++-type of
the memory location where the data is to be stored. By making the helpers
functions instead of macros, 'optional' parameters can be used reducing the
amount of helpers that are requires.

SLE_OBJECT_ADDRESS and SLE_GLOBAL_ADDRESS are introduced as helper macros to
both return the address of the variable, but also extra the variable type in
one simple lambda. C++ member functions seem as a viable alternative at first
glance, but sadly they do not support sub-structs. In other words: &Base::var
works fine but &Base::cont.var does not work at all.
To achieve this the AddressFunction needs to return the type, meaning we need
to do an ugly cast to remove the type information so we can store it as a
simple function pointer instead of a function object.
2026-09-15 20:57:48 +02:00
Rubidiumandrubidium42 0c0b63a6ec Codechange: export value_type for Dimension, so saveload can infer its array type 2026-09-15 20:57:48 +02:00
Peter NelsonandGitHub ecbe2aa17c Fix: Limit vehicle reliability to the model's current maximum reliability (#15879) 2026-09-15 17:11:16 +01:00
Peter NelsonandPeter Nelson 177a60b87e Change: Allow timetable window to be smaller 2026-09-15 17:03:09 +01:00
Peter NelsonandPeter Nelson bbd2c3e70e Change: Allow orders window to be smaller 2026-09-15 17:03:09 +01:00
Peter NelsonandGitHub 2838499563 Fix #15759: Inconsistency in disabled electric rails compatibility (#15994)
Electric trains built before disabling electric rail can run on regular rails after it is reenabled.
Electric trains built during electric rails being disabled could not.
2026-09-15 17:02:09 +01:00
Cyprian KlimaszewskiandGitHub 5d18b7cca7 Change: Allow admin to join any company in all interfaces (#15992) 2026-09-15 07:54:38 -04:00
Koen BussemakerandKuhnovic 3d137db87f Feature: Double-ended ships 2026-09-15 06:56:12 +02:00
Peter NelsonandGitHub 83d286383e Fix: Reducing a vehicle's cargo capacity incorrectly truncated the cargo. (#16004)
Truncate() accepts the amount to remove, not the new cargo capacity.
2026-09-13 10:01:56 +01:00
translators 0c2e7ec534 Update: Translations from eints
norwegian (bokmal): 2 changes by eriksorngard
2026-09-12 08:48:26 +00:00
Peter NelsonandPeter Nelson ddb284e074 Codechange: [Script] Add brief unit tests for -1 result 2026-09-11 20:46:33 +01:00
SamuXarickandPeter Nelson 79e679604a Fix #15506: Avoid ternary signed/unsigned conversion when returning literal -1 2026-09-11 20:46:33 +01:00
translators ee2b2ac12a Update: Translations from eints
czech: 1 change by adamek0202
2026-09-11 09:05:22 +00:00
Peter NelsonandGitHub 34919f318f Change: Allow font size to be changed with default truetype font (#16000) 2026-09-11 07:34:41 +01:00
Peter NelsonandGitHub 1c28b656a4 Codechange: Don't include strings.h from another general header (#15999) 2026-09-10 23:52:24 +01:00
Peter NelsonandGitHub d1af18d1b6 Codechange: Remove unnecessary chrono include (#15996) 2026-09-10 08:17:00 +01:00
Peter NelsonandGitHub bea6ddec8e Codechange: Remove unused Clone() member from TileArea (#15995) 2026-09-10 08:16:40 +01:00
Peter NelsonandPeter Nelson 18fc940ebf Codechange: Use common pattern for one-shot debug messages 2026-09-09 20:38:23 +01:00
Peter NelsonandPeter Nelson 2e5440e1c6 Codechange: Use scoped enum for debug facility instead of string 2026-09-09 20:38:23 +01:00
Peter NelsonandPeter Nelson 1672405e76 Codechange: Make debug severity level a scoped enum 2026-09-09 20:38:23 +01:00
Cyprian KlimaszewskiandGitHub f11e556d9c Codefix ff708c2c: The message in comment was inverted (#15993) 2026-09-09 11:37:11 -04:00
Peter NelsonandGitHub 1ea8a4cab1 Fix #15990, c9cf141813: Game crash when clearing up crashed train with last wagon in depot (#15991) 2026-09-08 18:15:31 +01:00
Cyprian KlimaszewskiandGitHub 8cc4832744 Fix #15863: Train should not clear path reservation under the other train that crashed into its front. (#15980) 2026-09-08 18:05:27 +01:00
Peter NelsonandGitHub de306de893 Fix #15985: Incorrect train station area after adding to a station (#15986) 2026-09-07 21:45:40 +01:00
translators b28429e71a Update: Translations from eints
catalan: 2 changes by J0anJosep
2026-09-07 09:39:38 +00:00
Peter NelsonandGitHub dc39225d60 Codechange: Replace StationRect with TileArea (#15979)
Allows re-use of existing functions that take TileArea.
2026-09-07 08:04:06 +01:00
Peter NelsonandGitHub 141b4e5eec Fix d89d6831: Crash when placing trees on coast tiles with rocks (#15984) 2026-09-07 07:55:07 +01:00
Peter NelsonandPeter Nelson 898eb92f3f Codechange: When using font console command, reload only the changed font 2026-09-05 07:34:21 +01:00
Peter NelsonandPeter Nelson b0ca968a34 Codechange: Pass font sizes when checking for missing glyphs
Instead of hard-coding the font sizes into the font searcher, pass a parameter. This allows performing a partial search, and reduces code.
2026-09-05 07:34:21 +01:00
Peter NelsonandGitHub 2701268c3e Change: Don't require glyphs for non-breaking space characters (#15982) 2026-09-04 23:05:19 +01:00
Peter NelsonandGitHub ed04d336ed Codefix: Too many closing braces in very unused #ifdef (#15978) 2026-09-03 19:29:36 +01:00
Peter NelsonandGitHub 604525bb5d Codechange: Add method to test if a TileArea is empty (#15981) 2026-09-03 19:22:50 +01:00
Peter NelsonandPeter Nelson 5232ea2f2d Codechange: Avoid redundant UpdateNearestTownForRoadTiles calls for JSON town import
Avoids two full map scans for every town placed, which is now done once per import.

Based on changes in JGRPP.
2026-09-03 17:51:43 +01:00
Peter NelsonandPeter Nelson a5183042d8 Codechange: Avoid second map scan for town roads if not required
Backported from JGRPP.
2026-09-03 17:51:43 +01:00
translators 28156aefe5 Update: Translations from eints
chinese (simplified): 2 changes by wensimehrp
esperanto: 2 changes by slashdevslashurandom
2026-09-03 09:09:09 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
39c8ac1459 Upgrade: Bump the actions group with 4 updates (#15977)
Bumps the actions group with 4 updates: [OpenTTD/actions](https://github.com/openttd/actions), [github/codeql-action](https://github.com/github/codeql-action), [OpenTTD/actions/.github/workflows/rw-cdn-upload.yml](https://github.com/openttd/actions) and [OpenTTD/actions/.github/workflows/rw-symbols-upload.yml](https://github.com/openttd/actions).


Updates `OpenTTD/actions` from 6 to 7
- [Release notes](https://github.com/openttd/actions/releases)
- [Commits](https://github.com/openttd/actions/compare/v6...v7)

Updates `github/codeql-action` from 4.37.3 to 4.37.9
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v4.37.3...v4.37.9)

Updates `OpenTTD/actions/.github/workflows/rw-cdn-upload.yml` from 6 to 7
- [Release notes](https://github.com/openttd/actions/releases)
- [Commits](https://github.com/openttd/actions/compare/v6...v7)

Updates `OpenTTD/actions/.github/workflows/rw-symbols-upload.yml` from 6 to 7
- [Release notes](https://github.com/openttd/actions/releases)
- [Commits](https://github.com/openttd/actions/compare/v6...v7)

---
updated-dependencies:
- dependency-name: OpenTTD/actions
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: github/codeql-action
  dependency-version: 4.37.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: OpenTTD/actions/.github/workflows/rw-cdn-upload.yml
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: OpenTTD/actions/.github/workflows/rw-symbols-upload.yml
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-02 15:34:28 +02:00
Peter NelsonandGitHub 22f653480b Change: Split json town importing from town creation. (#15972)
Parse all town data before attempting to create any towns.
2026-09-02 08:58:14 +01:00
Peter NelsonandGitHub 91e5f72f41 Fix #15636: Allow shift and ctrl modifiers in hotkeys (#15976) 2026-09-01 19:59:11 +01:00
translators 07d3061b6f Update: Translations from eints
english (us): 2 changes by 2TallTyler
2026-09-01 09:35:19 +00:00
Rubidiumandrubidium42 e5d5fdd4ac Codechange: store all Labels in 'GrfID' order
The order of 'GrfID' labels are reversed in the saves to their nominal order.
The order of rail/road type labels are in the same order in saves.

The choice to not go for the nominal order, but 'GrfID'/reverse order stems
from the impact on external tools. There are way more tools that interpret the
GrfIDs from the saves than there are tools that inspect the rail/road type
labels. As such, the 'GrfID' order is the lesser evil in unifying label order.
2026-09-01 09:55:56 +02:00
Peter NelsonandPeter Nelson 1c047a0f06 Change: [NewGRF] Validate airport tile layouts
Airport tile layouts are now validated just like industry tile layouts.
2026-08-31 22:33:00 +01:00
Peter NelsonandPeter Nelson e17f17565a Change: [NewGRF] Improve industry tile layout validation
* Invalid parts would be logged as ignored but not actually ignored.
* Missing check for valid original tile.
2026-08-31 22:33:00 +01:00
Peter NelsonandGitHub 2237b6b973 Fix #15233: Don't require glyphs for various whitespace characters (#15967)
Layouters contain logic to handle these codepoints without glyphs.
2026-08-31 20:51:20 +01:00
translators 96651d379a Update: Translations from eints
swedish: 2 changes by joeax910
2026-08-30 10:06:32 +00:00
Peter NelsonandGitHub 8d9b24cc1b Fix: Wrong button size in Bootstrap query window if game window resized (#15968) 2026-08-29 19:13:47 +01:00
Rubidiumandrubidium42 333d091d47 Codechange: 'inline' is implied by 'constexpr' 2026-08-29 13:34:50 +00:00
Rubidiumandrubidium42 d473c37f59 Codechange: 'static inline' over 'inline static' 2026-08-29 13:34:50 +00:00
Rubidiumandrubidium42 7a11bf6c17 Codechange: 'static constexpr' over 'constexpr static' 2026-08-29 13:34:50 +00:00
Rubidiumandrubidium42 262856ff4d Codechange: always quote strings in settings, removing the need for VarMemType::StrQ 2026-08-29 13:34:17 +00:00
Peter NelsonandGitHub a7755dbf7d Fix: Wrong category for some base set debug messages (#15965) 2026-08-29 12:59:13 +01:00
Peter NelsonandGitHub c251f51ef1 Codechange: Use AutoRelease to manage ubidi_open/close calls (#15964) 2026-08-29 09:55:42 +01:00
Peter NelsonandGitHub 43408dcf0e Change: Generate rough tiles as clusters like rocks (#15963) 2026-08-29 09:00:52 +01:00
translators 8a186962e5 Update: Translations from eints
english (au): 2 changes by krysclarke
chinese (traditional): 3 changes by KogentaSan
korean: 2 changes by telk5093
greek: 2 changes by gh658804
hungarian: 216 changes by meskobalazs
russian: 2 changes by Ln-Wolf
finnish: 2 changes by hpiirai
portuguese: 5 changes by jcteotonio
portuguese (brazilian): 2 changes by pasantoro
polish: 2 changes by pAter-exe
2026-08-28 16:53:35 +00:00
rubidium42andGitHub e604110351 Fix: invalidate/update vehicle caches when vehicle is marked dirty (#15946)
Ships already did this. The main reason is NewGRFs changing statistics about
vehicles when cargo is (un)loaded. Invalidating these caches cannot happen
only when the vehicle is done (un)loading, as the vehicle's maximum speed is
used in the cargo (un)loading logic for station rating.

In multiplayer a new client could get a different maximum speed because of
the changed amount of loaded cargo in the vehicle, changing the station's
rating with potential desyncs as a result. This all hinges on using a NewGRF
that changes the maximum speed based on the amount of loaded cargo.
2026-08-28 09:08:49 +01:00
Sören TempelandGitHub 122287992c Fix #15961: Don't pass a temporary object to BreakIterator::setText (#15962)
The API contract for BreakIterator::setText state the following:

> The BreakIterator will retain a reference to the supplied string. The
> caller must not modify or delete the text while the BreakIterator
> retains the reference.

However, presently, OpenTTD passes a temporary UnicodeString object
to this function. This object is destroyed as soon as the ->setText
expression was evaluated.

Therefore, this invocation violates the API contract and since the
UnicodeString destructor deallocates the underlying memory this can
cause an access to freed memory later on. To fix this, ensure that the
BreakIterator does not outlive the UnicodeString by using the same
lifetime for both objects.

Fixes #15961
2026-08-28 08:59:35 +01:00
Peter NelsonandPeter Nelson 7f45e4a34b Change: New coast and toyland rock overlay sprites 2026-08-26 21:07:04 +01:00
Peter NelsonandPeter Nelson 040aedcb92 Change: Place rocks randomly around lighthouses 2026-08-26 21:07:04 +01:00
Peter NelsonandPeter Nelson d89d6831ba Change: Add water and coastal rock tiles 2026-08-26 21:07:04 +01:00
translators a2533911dd Update: Translations from eints
indonesian: 23 changes by q1t0
2026-08-24 05:21:42 +00:00
translators 21c1e691ad Update: Translations from eints
chinese (simplified): 10 changes by xiaoliuprogrammer
indonesian: 39 changes by q1t0
2026-08-23 05:05:34 +00:00
Peter NelsonandGitHub 39da062c0c Codechange: Use ByteReader position to check industry definition size (#15959)
Avoids manually accounting for each byte that has been read.
2026-08-20 08:07:17 +01:00
translators 5fcd0fbee7 Update: Translations from eints
hungarian: 10 changes by vargaviktor
2026-08-20 05:07:49 +00:00
Peter NelsonandPeter Nelson 4d4f8bff38 Codechange: [NewGRF] Remove unneeded check for valid mapped entity IDs 2026-08-18 21:13:28 +01:00
Peter NelsonandPeter Nelson c3ee8ac11b Change: [NewGRF] Remove airport tile ID hole at 0xFF
Airport tiles have no special values that need to be avoided.
2026-08-18 21:13:28 +01:00
Peter NelsonandPeter Nelson 1b1a16c53b Change: [NewGRF] Remove object ID hole at 0xFF
Objects have no special values that need to be avoided.
2026-08-18 21:13:28 +01:00
Peter NelsonandPeter Nelson 4261255020 Change: [NewGRF] Remove industry tile ID hole at 0xFF
Change sentinel markers for water tile check and no animation to a value that is outside the valid ID range.
2026-08-18 21:13:28 +01:00
Peter NelsonandPeter Nelson 0f0fc477c9 Codechange: Use GFX_WATERTILE_SPECIALCHECK instead of magic numbers 2026-08-18 21:13:28 +01:00
Peter NelsonandPeter Nelson 77c82000e5 Codechange: Replace IndustryGraphics enum with constants
`IndustryGraphics` isn't a real enum, all of the values are actually `IndustryGfx` indices.

Also move them out of the map accessor header, because they are not map accessors.
2026-08-18 21:13:28 +01:00
Rubidiumandrubidium42 3a33cd64c9 Fix: autoclean empty time only checked at month boundary
In other words, if you joined a company at the 2nd and left the 27th, the
autoclean logic would not consider that company to have been in use for that
month. That would only happen if a client is present at the start of that
month. So, also reset this counter when a client joins the company.
2026-08-18 17:50:25 +02:00
translators 713994a0d6 Update: Translations from eints
swedish: 2 changes by Brickblock1
indonesian: 73 changes by q1t0
2026-08-17 05:12:34 +00:00
translators df55704e7d Update: Translations from eints
belarusian: 34 changes by GooseOb
2026-08-15 04:59:49 +00:00
Peter NelsonandGitHub 1b71d4c883 Change: Throw out per-grf industry tile limit. (#12183)
The industry tile limit was set based on the premise that action 3 ids might later be extended. They have since been extended.

Limit is now the total number of industry tiles that can be used.
2026-08-14 18:21:58 +01:00
Richard Wheeler 6b5173bfa5 Add: [NewGRF] Number of nearby stations for towns 2026-08-13 21:16:28 +01:00
Richard Wheeler ef223dca83 Add: [NewGRF] Town additional information 2026-08-13 20:10:55 +01:00
HyperJeanJeanandGitHub 667a12c0c6 Change: Use new game setting for disable_elrails when loading very old save (#14481)
Previous to this change, railways got automatically converted to
electric railway if there was any electric locomotive, as electric
railways could not be disabled until version 38
2026-08-13 07:22:47 -04:00
Richard Wheeler ada7ffaa73 Add: [NewGRF] Nearby tile info for towns 2026-08-13 11:23:06 +01:00
translators c1604a75c6 Update: Translations from eints
chinese (traditional): 4 changes by KogentaSan
czech: 486 changes by adamek0202
2026-08-13 06:01:50 +00:00
EmperorJakeandGitHub 9060a4a7ec Fix #15905: dual-headed engines show correct capacity when sorting (#15907)
Remove code that doubles the shown capacity of dual-headed engines when sorting the purchase list, as the given capacity is already doubled
2026-08-12 22:03:06 -04:00
Cyprian Klimaszewskiandrubidium42 cf584ea907 Codefix 93141cb: GCC 12.2.0 failed to compile 2026-08-12 20:35:46 +02:00
translators abf2843069 Update: Translations from eints
swedish: 36 changes by Brickblock1
2026-08-12 06:01:24 +00:00
Peter NelsonandGitHub be4f099c00 Codechange: Annotate override manager limits as const (#15952)
Makes it clear that these values do not change.
2026-08-10 20:24:07 +01:00
translators bb165f1e79 Update: Translations from eints
indonesian: 53 changes by q1t0
2026-08-10 05:58:54 +00:00
Loïc GuillouxandGitHub 987fab4bd6 Fix f673985: [MinGW] Undefined references in libsoxr (#15949) 2026-08-09 16:05:52 +00:00
translators 9b34939052 Update: Translations from eints
norwegian (bokmal): 10 changes by eriksorngard
indonesian: 275 changes by q1t0
maori (new zealand): 25 changes by Kyle-McDangersword
esperanto: 20 changes by slashdevslashurandom
polish: 1 change by pAter-exe
2026-08-09 05:31:44 +00:00
translators 8ef6fa58a8 Update: Translations from eints
indonesian: 72 changes by q1t0
2026-08-08 05:23:14 +00:00
Peter NelsonandGitHub 42a9a05a09 Codechange: Get road type for town bridge build attempt once (#15947) 2026-08-07 13:37:42 +01:00
Peter NelsonandPeter Nelson b05468a4dd Codechange: Remove macros from bridge sprite table initializers 2026-08-07 07:40:11 +01:00
Peter NelsonandPeter Nelson 7bc1e32b78 Codechange: Remove macro from bridge spec initializers 2026-08-07 07:40:11 +01:00
translators 3edd9a5a9b Update: Translations from eints
english (au): 10 changes by krysclarke
swedish: 9 changes by joeax910
chinese (traditional): 10 changes by KogentaSan
english (us): 10 changes by 2TallTyler
korean: 10 changes by telk5093
greek: 10 changes by gh658804
russian: 10 changes by Ln-Wolf
finnish: 11 changes by hpiirai
catalan: 10 changes by J0anJosep
portuguese: 10 changes by jcteotonio
portuguese (brazilian): 12 changes by pasantoro
polish: 10 changes by pAter-exe
2026-08-07 05:58:16 +00:00
Peter NelsonandGitHub ce14e19d89 Fix ba209c8745: Random company colours choice reversed (#15944) 2026-08-06 08:28:41 +01:00
Rubidiumandrubidium42 93141cbce1 Codechange: use ContiguousContainer for SlCopy and extract VarMemType 2026-08-05 11:55:54 +02:00
Cyprian Klimaszewskiandrubidium42 c2bafefe50 Codechange: Check costs instead of bank balance in marine and airport regression
Uses AIAccounting instead of AICompany::GetBankBalance.
2026-08-05 11:55:32 +02:00
Peter NelsonandGitHub f673985017 Add: Use LibSoxr for high quality sample-rate conversion (#15924)
If not present the existing but bad quality linear conversion can still be used.
2026-08-05 08:49:23 +01:00
translators 4c17039be7 Update: Translations from eints
swedish: 1 change by joeax910
2026-08-05 07:11:51 +00:00
Rubidiumandrubidium42 285937137b Codefix 3f04518f91: missing includes 2026-08-04 21:02:07 +02:00
Cyprian KlimaszewskiandGitHub 868d7df408 Codechange: Use AIAccounting instead of GetBankBalance() in terraforming regression (#15935) 2026-08-04 19:54:03 +02:00
BaricusandGitHub 3f04518f91 Add: Screensaver Mode (#15350)
This adds a simplistic "Screensaver Mode" under the about menu
which randomly picks between all vehicles on the map to follow, with a
bias towards moving vehicles.
2026-08-04 19:52:41 +02:00
5ad9d5f048 Change: [NewGRF] Ensure modflags bit 8 respects old behavior when train is driving backwards (#15485)
Co-authored-by: Tyler Trahan <tyler@tylertrahan.com>
2026-08-04 19:51:33 +02:00
Tad HardestyandGitHub f52d2e064a Add: Allow placing/erasing rough terrain in scenario editor (#15624) 2026-08-04 19:50:22 +02:00
TabytacandGitHub d328720ff5 Feature: Create new folders from the save dialog (#15730) 2026-08-04 19:49:07 +02:00
translators 30b5c8f68a Update: Translations from eints
norwegian (bokmal): 31 changes by eriksorngard
indonesian: 23 changes by q1t0
2026-08-03 07:56:39 +00:00
translators 00efe6a4ba Update: Translations from eints
chinese (simplified): 1 change by wensimehrp
2026-08-02 07:06:57 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
5fc9137e71 Upgrade: Bump the actions group with 2 updates (#15938)
Bumps the actions group with 2 updates: [github/codeql-action](https://github.com/github/codeql-action) and [microsoft/microsoft-store-apppublisher](https://github.com/microsoft/microsoft-store-apppublisher).


Updates `github/codeql-action` from 4 to 4.37.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v4...v4.37.3)

Updates `microsoft/microsoft-store-apppublisher` from 1.3 to 1.4
- [Release notes](https://github.com/microsoft/microsoft-store-apppublisher/releases)
- [Commits](https://github.com/microsoft/microsoft-store-apppublisher/compare/v1.3...v1.4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.37.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: microsoft/microsoft-store-apppublisher
  dependency-version: '1.4'
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-02 01:51:11 +02:00
translators 0de95fb529 Update: Translations from eints
chinese (simplified): 160 changes by wensimehrp
turkish: 6 changes by efemert124570
2026-08-01 07:02:36 +00:00
Peter NelsonandGitHub 840b13567d Codechange: Add and use Enum version of RandomRange() (#15929)
Allows getting a random value with less visible casting.
2026-07-31 22:38:54 +01:00
Peter NelsonandGitHub 4df104bc7d Codechange: Replace magic numbers with TreeGrowthStages (#15930) 2026-07-31 22:37:56 +01:00
metablasterandGitHub 60f80826ac Feature: [Script] AI API to remove rail depot (#15933) 2026-07-31 23:29:07 +02:00
translators 77ba2b244a Update: Translations from eints
chinese (simplified): 98 changes by wensimehrp
korean: 1 change by telk5093
afrikaans: 2 changes by chuckarrow
2026-07-31 07:22:12 +00:00
translators 19746b5c81 Update: Translations from eints
chinese (traditional): 1 change by KogentaSan
chinese (simplified): 154 changes by wensimehrp
catalan: 1 change by J0anJosep
2026-07-30 07:09:45 +00:00
Rubidiumandrubidium42 29f808ef00 Codechange: add Bool and Label aliases to VarFileType to denote intent 2026-07-29 10:39:02 +02:00
Tyler TrahanandGitHub 4ecbb871d1 Fix: Player-placed house protection for houses should override the callback (#14408) 2026-07-28 14:59:50 -04:00
Tyler TrahanandGitHub 97951cfcf2 Fix #15849: Rivers don't fill small seas with original land gen (#15852) 2026-07-28 14:58:57 -04:00
translators 308e75d74d Update: Translations from eints
english (au): 1 change by krysclarke
english (us): 1 change by 2TallTyler
greek: 1 change by gh658804
hungarian: 7 changes by vargaviktor
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
portuguese: 1 change by jcteotonio
portuguese (brazilian): 1 change by pasantoro
polish: 1 change by pAter-exe
2026-07-28 07:11:00 +00:00
Peter NelsonandGitHub a6b1b3ac44 Change: split reading of SpriteGroup types to separate functions (#15921)
Achieves what f9e6b8b7d aimed to do, as a read error will replace the current set id, but as it is only replaced at the end, chaining to the same set id works correctly.

Also reduces cognitive complexity.
2026-07-27 19:08:06 +01:00
Cyprian KlimaszewskiandGitHub eced18224a Codechange: Make Corner enum a scoped one (#15523) 2026-07-27 09:37:26 -04:00
Peter NelsonandGitHub d6848be640 Fix: Change the order that (Un)FlattenNewGRFLabel convert (#15918)
The most common usage for this function is to convert a DWord from NewGRF into a label.

Now the rare cases, sending over the network and script interaction, requires a std::byteswap.

This reverts commit 9140a7ad4a
2026-07-26 22:48:40 +01:00
Peter NelsonandGitHub b6f067cf36 Codechange: Use static_cast instead of C-cast in map accessors (#15920) 2026-07-26 19:47:09 +00:00
Rubidiumandrubidium42 252c239a14 Fix: potential off-by-one out of bounds read during saving 2026-07-26 19:17:18 +02:00
Peter NelsonandPeter Nelson 368ade294a Change: Move small map buttons to side of window
Uses a dynamic widget to switch the buttons between 1 and 2 column layout depending on height, and improves use of space.
2026-07-26 15:20:40 +01:00
Peter NelsonandPeter Nelson 12208d1204 Codechange: Widgets can use a preferred size based given size
This allows widgets to return a different size depending on the size that would be used, allowing for more dynamic sizing.
2026-07-26 15:20:40 +01:00
Peter NelsonandGitHub a68148f86f Change: account for driving cabs in driving backwards conditional order (#15494)
The condition is now "driving backwards at reduced speed".

If a train is able to run at full speed when driving backwards then there is no need to perform manoeuvres to turn around
2026-07-26 14:22:09 +01:00
Rubidiumandrubidium42 1bc8f44eab Codefix: use ubuntu-latest over ubuntu-24.04 2026-07-26 13:30:36 +02:00
Rubidiumandrubidium42 81d7025ab1 Codechange: do not use SlCopy to skip bytes that should not be read anymore 2026-07-26 11:26:02 +02:00
Peter NelsonandPeter Nelson d84089248a Codechange: Include ScriptEvent types only where needed 2026-07-26 10:17:09 +01:00
Peter NelsonandPeter Nelson 16b08092b4 Codechange: Add missing control codes include 2026-07-26 10:17:09 +01:00
Peter NelsonandPeter Nelson 9fbb32fb7a Codechange: Add missing widgets includes 2026-07-26 10:17:09 +01:00
Peter NelsonandPeter Nelson de65913055 Codechange: Refactor president name generation to avoid gotos 2026-07-26 10:16:55 +01:00
Peter NelsonandPeter Nelson e6ee076dc3 Change: Properly disallow duplicate company names.
Refactor company name generation to remove gotos, and check that names
are unique by string instead of just the seed parameter, which could
result in the same name.
2026-07-26 10:16:55 +01:00
Peter NelsonandGitHub 9140a7ad4a Fix #15902: NewGRF GEF ID checks failing (#15904)
GRF ID needs to be reversed when coming from a uint32_t.
2026-07-26 10:16:14 +01:00
Cyprian KlimaszewskiandPeter Nelson 9a6c4392ab Codechange: Replace out arguments in GetSlopePixelZOnEdge with a tuple 2026-07-26 10:12:27 +01:00
Cyprian KlimaszewskiandPeter Nelson cbf782c900 Codechange: Merge HasFoundationNW and HasFoundationNE into one function
The logic in both of them is simillar and they only differ in constant
values.
Both of them are only used once so when merged the reason for it not to
be inlined is back.
It is easier to document one function than two.
2026-07-26 10:12:27 +01:00
cirdanandPeter Nelson 4a59aadb8b Codechange: Add a helper function GetFoundationSpriteBlock
HasFoundationNW and HasFoundationNE were used in a similar way in
DrawFoundation and DrawTile_Station. Factor this usage out into
its own function GetFoundationSpriteBlock, which allows to make
HasFoundationNW and HasFoundationNE static.
2026-07-26 10:12:27 +01:00
Rubidiumandrubidium42 0753474676 Codechange: make AddressFunction more const, so less casting is required 2026-07-26 10:33:34 +02:00
translators 2a33c65404 Update: Translations from eints 2026-07-26 07:10:22 +00:00
Rubidiumandrubidium42 c4ba42cecb Codechange: make StringID a strong type 2026-07-25 21:30:29 +02:00
Rubidiumandrubidium42 793663f0cd Codechange: do not use StringID as template parameter 2026-07-25 21:30:29 +02:00
Rubidiumandrubidium42 b7c4443215 Codechange: move GoalQuestion window caption out of template into GetWidgetString 2026-07-25 21:30:29 +02:00
Tyler TrahanandGitHub 1f981d5338 Codefix: Rename breakdown setting value string (#15908) 2026-07-25 12:42:26 -04:00
Rubidiumandrubidium42 ec978b0e0a Codechange: move SaveLoadAddrProc to SaveLoad::AddressFunction 2026-07-25 18:36:15 +02:00
Rubidiumandrubidium42 41dbebf7e9 Codechange: use ranged-for loops to save/load the map arrays 2026-07-25 18:36:00 +02:00
Rubidiumandrubidium42 259d75e2e5 Codefix: simplify resize logic 2026-07-25 17:36:57 +02:00
translators f823a9af5d Update: Translations from eints
hungarian: 17 changes by vargaviktor
2026-07-25 06:37:28 +00:00
Peter NelsonandGitHub 7f1946f996 Fix: Coast tiles shown as water tiles in small map (#15883) 2026-07-24 19:02:09 +01:00
translators 9130c591dc Update: Translations from eints
english (us): 9 changes by 2TallTyler
indonesian: 1 change by q1t0
maori (new zealand): 5 changes by Kyle-McDangersword
2026-07-23 07:05:08 +00:00
translators 0500bfdece Update: Translations from eints
english (au): 9 changes by krysclarke
korean: 9 changes by telk5093
catalan: 82 changes by J0anJosep
polish: 1 change by pAter-exe
2026-07-22 07:07:39 +00:00
Rubidiumandrubidium42 d953f27dd9 Codefix: do not copy widget parts while iterating 2026-07-21 21:15:24 +02:00
Peter NelsonandGitHub bd41367e3c Fix 80d0c7763: Game information not showing in Load Game window (#15891)
Inverted test while reading chunks skipped file.
2026-07-21 19:07:03 +00:00
translators 25ec12c62d Update: Translations from eints
chinese (traditional): 17 changes by KogentaSan
greek: 9 changes by gh658804
russian: 1 change by Ln-Wolf
finnish: 12 changes by hpiirai
maori (new zealand): 358 changes by Kyle-McDangersword
catalan: 163 changes by J0anJosep
portuguese: 12 changes by jcteotonio
portuguese (brazilian): 1 change by pasantoro
polish: 22 changes by pAter-exe
2026-07-21 07:06:04 +00:00
Peter NelsonandGitHub ae35d8223f Codefix: Incorrect include guard for script_story_page.hpp (#15887) 2026-07-20 23:31:36 +01:00
Cyprian KlimaszewskiandGitHub dda399faf3 Codefix: Compilation fails on VS2022 (#15871) 2026-07-20 14:23:03 +02:00
translators c7cacf0752 Update: Translations from eints
maori (new zealand): 421 changes by Kyle-McDangersword
2026-07-20 07:40:49 +00:00
Cyprian KlimaszewskiandGitHub 7e7223d9b0 Codechange: Do not allow size_t indexing for Slope indexed arrays (#15821) 2026-07-20 07:26:51 +01:00
Peter NelsonandGitHub ea2f024c03 Codechange: Pass smallmap colour mask by reference (#15882) 2026-07-20 07:18:21 +01:00
Peter NelsonandGitHub eef236e480 Change: Update wording of force unload order (#15880) 2026-07-19 20:41:47 +01:00
Peter NelsonandPeter Nelson 198893a04a Codechange: Use EnumIndexArray for smallmap TileType lookup tables
There is no need to use a custom container of size `TileType::End + 1`, and no need to include an unused dummy value
2026-07-19 20:40:29 +01:00
Peter NelsonandPeter Nelson 66aea1f5d9 Codechange: Use EnumIndexArray for smallmap vegetation lookup table 2026-07-19 20:40:29 +01:00
Rubidiumandrubidium42 c0762f2c26 Codechange: use std::array over C-style arrays for saved data 2026-07-19 09:39:21 +02:00
Rubidiumandrubidium42 c40d482783 Codefix: given memory type in SaveLoad does not always match variable 2026-07-19 09:38:24 +02:00
translators 4ca37d0340 Update: Translations from eints
maori (new zealand): 151 changes by Kyle-McDangersword
2026-07-19 07:04:43 +00:00
Peter Nelsonandrubidium42 97e6800287 Fix #15877: Rail/road type labels are stored forwards, not in reverse.
Explicitly specify whether a label should be saved/loaded forward or reverse for backwards compatibility.
2026-07-19 07:30:42 +02:00
Peter NelsonandGitHub f9699cc6a1 Codechange: Use signed arithmetic in engine reliability (#15875)
Avoids underflowing unsigned values and extra casts.
2026-07-18 21:08:18 +01:00
translators c876c59d41 Update: Translations from eints
maori (new zealand): 4 changes by Kyle-McDangersword
catalan: 36 changes by J0anJosep
2026-07-18 06:28:18 +00:00
Rubidiumandrubidium42 eb62295cc0 Codechange: expose saveload.h less to the rest of the game 2026-07-17 19:53:59 +02:00
translators 6892b8a463 Update: Translations from eints
swedish: 7 changes by Brickblock1
2026-07-17 06:36:39 +00:00
Rubidiumandrubidium42 9a02ac21e8 Codechange: let GrfID be a Label 2026-07-16 19:54:53 +02:00
Rubidiumandrubidium42 5298a18418 Fix fa4b9819c0: endianness issues with saving of labels 2026-07-16 19:05:06 +02:00
Cyprian KlimaszewskiandGitHub 5b9f18d8fd Codefix #15828: set was renamed to density only in source file (#15865) 2026-07-16 09:50:51 +00:00
translators d97005e31e Update: Translations from eints
estonian: 17 changes by JooReb
catalan: 113 changes by J0anJosep
2026-07-16 06:41:28 +00:00
Peter NelsonandGitHub 3f2f61c49b Codechange: Make TextfileType a scoped enum (#15864) 2026-07-15 23:21:59 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
162c629766 Upgrade: Bump the actions group with 3 updates (#15816)
Bumps the actions group with 3 updates: [actions/checkout](https://github.com/actions/checkout), [actions/cache](https://github.com/actions/cache) and [cloudflare/wrangler-action](https://github.com/cloudflare/wrangler-action).


Updates `actions/checkout` from 6 to 7
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)

Updates `actions/cache` from 5 to 6
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v5...v6)

Updates `cloudflare/wrangler-action` from 3 to 4
- [Release notes](https://github.com/cloudflare/wrangler-action/releases)
- [Changelog](https://github.com/cloudflare/wrangler-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/cloudflare/wrangler-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/cache
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: cloudflare/wrangler-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-15 23:29:04 +02:00
Tyler TrahanandGitHub 9bea75a8d1 Codechange: Use sprite array instead of magic number for snowy rocks (#15835) 2026-07-15 15:10:35 -04:00
Rubidiumandrubidium42 150da36869 Codechange: remove compiler flags allowing multi character literals 2026-07-15 20:07:08 +02:00
Rubidiumandrubidium42 e065da15ff Codechange: remove multichar literals from FillSetDetails 2026-07-15 19:13:18 +02:00
Rubidiumandrubidium42 2d48e82bbb Codechange: remove unneeded packing of ChunkHeader and WAVE_DOWNLOAD 2026-07-15 18:07:49 +02:00
Rubidiumandrubidium42 fa4b9819c0 Codechange: use Label for CargoLabel, RailTypeLabel and RoadTypeLabel 2026-07-15 18:07:22 +02:00
Jonathan G RennisonandGitHub 7126fcafcc Fix: Rail depot overbuild did not handle associated reservation (#15860) 2026-07-15 07:40:37 -04:00
translators 659208ab57 Update: Translations from eints
estonian: 30 changes by JooReb
catalan: 84 changes by J0anJosep
2026-07-15 06:36:15 +00:00
Rubidiumandrubidium42 143af1098d Codechange: remove support for ICC (Intel's deprecated compiler) 2026-07-14 19:47:06 +02:00
Rubidiumandrubidium42 68f5a8a0fd Codechange: use Label for Action14 NodeID 2026-07-14 18:27:28 +02:00
Rubidiumandrubidium42 121df5b461 Codechange: simplify BMP header creation 2026-07-14 18:27:14 +02:00
Rubidiumandrubidium42 1d1c603494 Codechange: use Label for NewGRF class global ids 2026-07-14 14:04:54 +02:00
Rubidiumandrubidium42 af60d6b7cd Codechange: use Label for the tags in a Wave file 2026-07-14 12:46:14 +02:00
Rubidiumandrubidium42 fe31736981 Codechange: use Label for the SaveLoadFormatTag over multi-character-literals 2026-07-14 11:49:15 +02:00
Rubidiumandrubidium42 80d0c7763a Codechange: use Label for the ChunkId over multi-character-literals 2026-07-14 11:49:15 +02:00
translators 6b553caa74 Update: Translations from eints
hungarian: 3 changes by vargaviktor
2026-07-14 06:34:46 +00:00
Peter NelsonandPeter Nelson 2c48b1efb9 Change: limit purchase list rows to 1.5x original design height 2026-07-13 23:15:08 +01:00
Peter NelsonandPeter Nelson e3dfd59df0 Change: clip content in purchase list to each row 2026-07-13 23:15:08 +01:00
EnovaandGitHub 0366278c9d Codechange: Support ID_LIKE in build targeting (#15818) 2026-07-13 23:15:22 +02:00
Rubidiumandrubidium42 808ae7f270 Codechange: [Windows] Use SetThreadDescription over magic exception 2026-07-13 18:41:39 +02:00
translators d1ec9f4897 Update: Translations from eints
english (au): 7 changes by krysclarke
chinese (traditional): 12 changes by KogentaSan
english (us): 13 changes by 2TallTyler
korean: 17 changes by telk5093
greek: 7 changes by gh658804
hungarian: 4 changes by vargaviktor
russian: 13 changes by Ln-Wolf
finnish: 18 changes by hpiirai
maori (new zealand): 17 changes by Kyle-McDangersword
turkish: 34 changes by jnmbk
portuguese: 8 changes by jcteotonio
esperanto: 18 changes by slashdevslashurandom
portuguese (brazilian): 7 changes by pasantoro
2026-07-13 07:48:17 +00:00
Peter NelsonandGitHub 922d38f1c0 Codechange: Make IniFileVersion a scoped enum and format comments similar to SaveLoadVersion (#15848) 2026-07-12 19:28:06 +01:00
Peter NelsonandGitHub e4620d5832 Doc: Update changelog for 16.0-beta2 (#15844) 2026-07-12 13:51:23 +01:00
translators cf48f866eb Update: Translations from eints
english (au): 6 changes by krysclarke
swedish: 20 changes by joeax910
chinese (traditional): 6 changes by KogentaSan
greek: 6 changes by gh658804
maori (new zealand): 10 changes by Kyle-McDangersword
portuguese: 6 changes by jcteotonio
portuguese (brazilian): 6 changes by pasantoro
polish: 4 changes by Rito13
2026-07-12 07:07:44 +00:00
Peter NelsonandGitHub 3c30f962d4 Fix: Use meaningful tooltips for graph range toggle buttons (#15842)
Previously the tooltip only mentioned toggling the cargo, which is only correct for the cargo toggle buttons.
2026-07-11 13:51:01 +01:00
translators 3fb3006dff Update: Translations from eints
english (au): 4 changes by krysclarke
chinese (traditional): 4 changes by KogentaSan
english (us): 4 changes by 2TallTyler
greek: 4 changes by gh658804
russian: 4 changes by Ln-Wolf
danish: 15 changes by bscargo
portuguese: 4 changes by jcteotonio
portuguese (brazilian): 3 changes by pasantoro, 1 change by jcteotonio
2026-07-11 06:34:16 +00:00
Charles PigottandGitHub 0ab5b6df1b Feature: Increase maximum number of vehicles per type to 10,000 (#15810) 2026-07-10 12:11:36 +01:00
mmtunligitandGitHub a961e64928 Add: Adding and removing whole classes to collections (#15808) 2026-07-10 06:54:50 -04:00
translators 9f8ac2aaa1 Update: Translations from eints
indonesian: 86 changes by q1t0
2026-07-10 07:59:11 +00:00
Rubidiumandrubidium42 0c6de46b4c Codechange: unify logging of GrfIDs 2026-07-10 09:51:02 +02:00
Peter NelsonandGitHub 83f20c3375 Doc: Changelog for 16.0-beta1 was missing Markdown formatting (#15840) 2026-07-10 00:00:53 +01:00
Peter NelsonandGitHub 85e6f020f9 Change: Use "bridge ... too low" message for bridgeable objects (#15838) 2026-07-09 19:56:06 +01:00
Peter NelsonandGitHub 83ce49f6cb Feature: Allow bridges over depots (#15836)
Depots are somewhat tall, so bridges must be at least 3 height levels above them.
2026-07-09 18:26:13 +01:00
translators 44b51a94c5 Update: Translations from eints
estonian: 417 changes by JooReb
2026-07-09 07:59:14 +00:00
Peter NelsonandGitHub f5e4bd1ed7 Fix #15826: Exclude allow any/all options for AI companies (#15834) 2026-07-09 00:20:07 +00:00
Rubidiumandrubidium42 5303aa6516 Codechange: use const for writing savegame data 2026-07-09 02:01:13 +02:00
Peter NelsonandGitHub 5403257dca Codechange: Don't calculate bridge height difference twice (#15831) 2026-07-08 22:23:55 +01:00
Rubidiumandrubidium42 05e596661e Codechange: move VarType constants into 'VarTypes' 2026-07-08 17:51:45 +02:00
Tyler TrahanandGitHub e95f43a720 Codechange: Use sprite table instead of magic number when drawing ground sprite (#15828) 2026-07-08 08:46:21 -04:00
translators 51af63cc9f Update: Translations from eints
english (us): 4 changes by 2TallTyler
estonian: 182 changes by JooReb
maori (new zealand): 2 changes by Kyle-McDangersword
2026-07-08 06:45:25 +00:00
Cyprian KlimaszewskiandGitHub 8e89414d9e Codechange: Add regression tests for terraforming and its costs (#15820) 2026-07-07 16:19:14 -04:00
Tyler TrahanandGitHub 24333d76a9 Codefix: Clean up rocky ground placement in Editor (#15819) 2026-07-07 16:17:19 -04:00
verbosecodesandrubidium42 ac51eab537 Fix #7992: Fix for catenary road and tram catenary sprites not being drawn on bridges 2026-07-07 21:27:52 +02:00
translators 0f09b4b371 Update: Translations from eints
swedish: 8 changes by Brickblock1
korean: 3 changes by telk5093
maori (new zealand): 5 changes by Kyle-McDangersword
2026-07-07 07:58:44 +00:00
Rubidiumandrubidium42 bf7bb3efaf Codechange: add missing documentation 2026-07-06 16:41:08 +02:00
Rubidiumandrubidium42 9ba2e386ac Codechange: use GrfID over uint32_t for NewGRF IDs 2026-07-06 16:41:08 +02:00
translators 21d9af637a Update: Translations from eints
swedish: 3 changes by Brickblock1
2026-07-06 08:46:35 +00:00
translators 788e112be1 Update: Translations from eints
english (au): 4 changes by krysclarke
swedish: 4 changes by Brickblock1
chinese (traditional): 5 changes by KogentaSan
greek: 4 changes by gh658804
russian: 1 change by Ln-Wolf
finnish: 4 changes by hpiirai
maori (new zealand): 16 changes by Kyle-McDangersword
portuguese: 4 changes by jcteotonio
portuguese (brazilian): 4 changes by pasantoro
polish: 4 changes by pAter-exe
2026-07-05 07:45:33 +00:00
translators bf70c61fb8 Update: Translations from eints
maori (new zealand): 24 changes by Kyle-McDangersword
2026-07-04 07:21:48 +00:00
livingBEEFandGitHub c18b3a8a04 Fix traffic side inconsistencies (#15661)
* Update: change wording for driving side setting

* Fix: [NewGRF] Make 'signals on traffic side' consistent with explicit settings

Previously this TTDPatchFlag returned 'true' when the 'train signal side'
setting was 'road vehicle driving side'. Now it will also return 'true' when
both the settings are the same, i.e. both are 'left' or both are 'right'.
2026-07-03 08:21:23 -04:00
translators 8e08f1a3c5 Update: Translations from eints
hungarian: 1 change by vargaviktor
maori (new zealand): 14 changes by Kyle-McDangersword
2026-07-03 07:46:16 +00:00
Rubidiumandrubidium42 8303b2d694 Codechange: document gamelog_internal.h 2026-07-02 14:40:52 +02:00
translators 4d7e1385f9 Update: Translations from eints
indonesian: 75 changes by q1t0
maori (new zealand): 11 changes by Kyle-McDangersword
2026-07-02 05:49:00 +00:00
Rubidiumandrubidium42 d2a3f52257 Codechange: improve documentation by removing unneeded constructors/operators 2026-07-01 21:05:56 +02:00
translators 01919af55b Update: Translations from eints
maori (new zealand): 68 changes by Kyle-McDangersword
2026-07-01 06:02:27 +00:00
translators 9c3f5bc375 Update: Translations from eints
indonesian: 29 changes by q1t0
2026-06-30 05:55:38 +00:00
Rubidiumandrubidium42 0a9aa3d20b Codechange: make VarMemType scoped 2026-06-30 00:19:27 +02:00
Rubidiumandrubidium42 8db7db5569 Codechange: make VarFileType scoped 2026-06-30 00:19:27 +02:00
Rubidiumandrubidium42 d9d7f441db Codechange: make SLRefType scoped 2026-06-30 00:19:27 +02:00
Rubidiumandrubidium42 76265b8451 Codechange: replace SaveLoadFlags with StringValidationSettings 2026-06-29 23:33:13 +02:00
Rubidiumandrubidium42 1310531139 Codechange: replace GetVarFileType with just direct member access 2026-06-29 19:56:06 +02:00
Rubidiumandrubidium42 0bd12558d4 Codechange: replace GetVarMemType with just direct struct member access 2026-06-29 19:56:06 +02:00
Rubidiumandrubidium42 bdbe305771 Codechange: make SlVarSize, ReadValue and WriteValue use VarMemType 2026-06-29 19:56:06 +02:00
Rubidiumandrubidium42 71ca79c6d5 Codechange: split up VarTypes in separate enumerations and recombine as struct 2026-06-29 19:56:06 +02:00
Rubidiumandrubidium42 afbe2d3070 Codechange: unify order of file and variable saveload configuration 2026-06-29 19:56:06 +02:00
Rubidiumandrubidium42 f72a239b97 Codechange: make SaveFileType clearly distinct from VarType 2026-06-29 19:56:06 +02:00
Rubidiumandrubidium42 df20fed464 Codechange: replace GRFBaseLanguages with an EnumBitSet 2026-06-29 09:09:28 +02:00
Rubidiumandrubidium42 af1e9864a0 Codechange: replace GRFExtendedLanguages with scoped enum GRFLanguage 2026-06-29 09:09:28 +02:00
Peter NelsonandPeter Nelson 3f557fb673 Codechange: make NeedLength a scoped enum. 2026-06-29 07:41:41 +01:00
Peter NelsonandPeter Nelson 36551ba6b5 Codechange: make SaveLoadAction a scoped enum 2026-06-29 07:41:25 +01:00
Peter NelsonandGitHub 11f46bc5f4 Fix: explicitly initialize COM in Win32 video driver (#15553) 2026-06-29 07:40:03 +01:00
Peter NelsonandPeter Nelson 099df1054e Codechange: make TileContext a scoped enum 2026-06-29 07:35:19 +01:00
Peter NelsonandPeter Nelson d3d1de822d Codechange: make Action5BlockType a scoped enum 2026-06-29 07:30:02 +01:00
Rubidiumandrubidium42 ef0d26f9f7 Codechange: properly decode VarType to determine whether the maximum value fits in the type 2026-06-29 08:11:12 +02:00
Rubidiumandrubidium42 8a8ece49ec Codechange: simplify/shrink SaveLoadCompat
Remove the unneeded null_type and change the name to std::string_view
2026-06-29 08:10:02 +02:00
Rubidiumandrubidium42 a01a2f8401 Codechange: remove essentially pointless 'shortcut values' 2026-06-29 08:09:31 +02:00
Rubidiumandrubidium42 d0dcd1b134 Codechange: use SLE_INT8 instead of SLE_CHAR 2026-06-29 08:09:31 +02:00
Rubidiumandrubidium42 a5430717b1 Codechange: prefer SLE_INT32 over SLE_INT 2026-06-29 08:09:31 +02:00
Rubidiumandrubidium42 c367b10bde Codechange: prefer SLE_UINT32 over SLE_UINT 2026-06-29 08:09:31 +02:00
Peter NelsonandPeter Nelson 2934eca24a Codechange: make TownCargoGenMode a scoped enum 2026-06-28 20:48:11 +01:00
Peter NelsonandPeter Nelson 02becd50c5 Codechange: make TownFounding a scoped enum 2026-06-28 20:48:11 +01:00
Peter NelsonandPeter Nelson 3ba0706a5c Codechange: make TownLayout a scoped enum 2026-06-28 20:48:11 +01:00
Peter NelsonandPeter Nelson 1acbb1c654 Codechange: make TownSize a scoped enum 2026-06-28 20:48:11 +01:00
Peter NelsonandPeter Nelson 6f6551c08d Codechange: Use general Alignment for intro game viewport commands 2026-06-28 20:43:36 +01:00
Peter NelsonandPeter Nelson b4d16d319f Codechange: Replace Alignment enum with struct
Alignment struct contains separate horizontal and vertical alignment members.
2026-06-28 20:43:36 +01:00
Peter NelsonandPeter Nelson 8e637cefed Codechange: Rename StringAlignment to Alignment
Alignment is also used things other than strings.
2026-06-28 20:43:36 +01:00
Peter NelsonandGitHub 5923d105ec Revert: "Fix: [NewGRF] Ensure Act2 read error replaces current set id (#15782)" (#15795)
This reverts commit f9e6b8b7dd.
2026-06-28 19:35:09 +00:00
Rubidiumandrubidium42 a76ba0d3d4 Codechange: make ChunkType scoped 2026-06-28 21:07:12 +02:00
Rubidiumandrubidium42 b7d07252e7 Codechange: make SaveLoadType scoped 2026-06-28 19:26:21 +02:00
Rubidiumandrubidium42 f8af6bbc2f Codechange: make OpenGLSprite::Texture scoped 2026-06-28 19:25:45 +02:00
Rubidiumandrubidium42 8b83bac31f Codechange: make SavegameType scoped 2026-06-28 17:49:19 +02:00
Peter NelsonandPeter Nelson b02242d5fc Codechange: make RandomizedSpriteGroupCompareMode a scoped enum 2026-06-28 16:21:01 +01:00
Peter NelsonandPeter Nelson 4344ffb7a0 Codechange: make DeterministicSpriteGroupAdjustOperation a scoped enum 2026-06-28 16:21:01 +01:00
Peter NelsonandPeter Nelson 4e9645e9d0 Codechange: make DeterministicSpriteGroupAdjustType a scoped enum 2026-06-28 16:21:01 +01:00
Peter NelsonandPeter Nelson 947767a2ff Codechange: make DeterministicSpriteGroupSize a scoped enum 2026-06-28 16:21:01 +01:00
Peter NelsonandPeter Nelson 4b93bd74ef Codechange: make VarSpriteGroupScope a scoped enum 2026-06-28 16:21:01 +01:00
Rubidiumandrubidium42 061e5c9cd3 Codechange: use helper for common mappings using PerformanceElement::AI0 2026-06-28 16:55:28 +02:00
Rubidiumandrubidium42 5b3b7995bb Codechange: make PerformanceElement scoped 2026-06-28 16:55:28 +02:00
Peter NelsonandGitHub 3666eb23a1 Fix #15784: Do close and reopen road build toolbar when switching road tram types (#15789) 2026-06-28 07:08:13 +00:00
Peter NelsonandGitHub f9e6b8b7dd Fix: [NewGRF] Ensure Act2 read error replaces current set id (#15782) 2026-06-28 08:07:09 +01:00
translators 2a6a65662d Update: Translations from eints
indonesian: 117 changes by q1t0
2026-06-28 05:59:00 +00:00
Peter NelsonandGitHub b7e693ced6 Codechange: no need to pre-declare local variables (#15781) 2026-06-27 18:31:50 +01:00
rubidium42andGitHub b9986cdadf Change: upgrade emscripten from 3.1.57 to 6.0.1 (#15780) 2026-06-27 16:00:51 +01:00
Cyprian KlimaszewskiandGitHub dc87cd3d7a Codechange: Use more helper functions for slopes. (#15722) 2026-06-27 10:17:48 -04:00
Rubidiumandrubidium42 8ca99f96ee Codechange: remove macros for SDLVkMapping 2026-06-27 16:14:27 +02:00
Rubidiumandrubidium42 790a6903af Codechange: document several SDL members 2026-06-27 16:14:16 +02:00
mmtunligitandrubidium42 98dfc7376c Codechange: Split long single line loop to match #15589 2026-06-26 18:26:01 +02:00
Rubidiumandrubidium42 cc92e3d421 Codechange: make 32bpp blitter enumerations scoped 2026-06-26 17:33:15 +02:00
Rubidiumandrubidium42 42fe1133ad Doc: make obvious what the numbers in SaveLoadVersion mean, especially in the generated doxygen 2026-06-26 13:04:33 +02:00
Rubidiumandrubidium42 fc0ad4bb0a Codechange: remove unneeded spaces 2026-06-26 13:04:33 +02:00
Rubidiumandrubidium42 5bb87d39b7 Codechange: make SaveLoadVersion a scoped enum 2026-06-26 13:04:33 +02:00
translators f8ad1a4999 Update: Translations from eints
polish: 17 changes by pAter-exe
2026-06-26 05:55:39 +00:00
Rubidiumandrubidium42 f0a1b507fe Codechange: make ClientID a scoped enumeration 2026-06-26 06:26:52 +02:00
Rubidiumandrubidium42 2f4ae80226 Codechange: use ClientID for the 'user' of OrderBackup 2026-06-25 23:57:45 +02:00
Peter NelsonandGitHub 11e713ce9a Add: Station list can be filtered by name (#15772) 2026-06-25 22:28:21 +01:00
654 changed files with 16652 additions and 13976 deletions
+1 -1
View File
@@ -105,4 +105,4 @@ jobs:
steps:
- name: Check annotations
uses: OpenTTD/actions/annotation-check@v6
uses: OpenTTD/actions/annotation-check@v7
+4 -11
View File
@@ -14,30 +14,23 @@ jobs:
container:
# If you change this version, change the numbers in the cache step,
# .github/workflows/preview-build.yml (2x) and os/emscripten/Dockerfile too.
image: emscripten/emsdk:3.1.57
image: emscripten/emsdk:6.0.1
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Fix dubious ownership
run: |
git config --global --add safe.directory ${GITHUB_WORKSPACE}
- name: Update to modern GCC
run: |
apt-get update
apt-get install -y gcc-12 g++-12
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 100
- name: Setup cache
uses: actions/cache@v5
uses: actions/cache@v6
with:
# If you change this version, change the numbers in the image configuration step,
# .github/workflows/preview-build.yml (2x) and os/emscripten/Dockerfile too.
path: /emsdk/upstream/emscripten/cache
key: 3.1.57-${{ runner.os }}
key: 6.0.1-${{ runner.os }}
- name: Add liblzma support
run: |
+4 -3
View File
@@ -23,18 +23,18 @@ jobs:
linux:
name: CI
runs-on: ubuntu-24.04
runs-on: ubuntu-latest
env:
CC: ${{ inputs.compiler }}
CXX: ${{ inputs.cxxcompiler }}
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Setup vcpkg
id: vcpkg
uses: OpenTTD/actions/setup-vcpkg@v6
uses: OpenTTD/actions/setup-vcpkg@v7
- name: Install dependencies
run: |
@@ -54,6 +54,7 @@ jobs:
libogg-dev \
libopus-dev \
libopusfile-dev \
libsoxr-dev \
${{ inputs.libraries }} \
zlib1g-dev \
# EOF
+2 -2
View File
@@ -32,11 +32,11 @@ jobs:
xcode-version: latest-stable
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Setup vcpkg
id: vcpkg
uses: OpenTTD/actions/setup-vcpkg@v6
uses: OpenTTD/actions/setup-vcpkg@v7
- name: Install OpenGFX
run: |
+2 -1
View File
@@ -21,7 +21,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
@@ -41,6 +41,7 @@ jobs:
libogg:p
opus:p
opusfile:p
libsoxr:p
- name: Install OpenGFX
shell: bash
+1 -1
View File
@@ -55,4 +55,4 @@ jobs:
steps:
- name: Check annotations
uses: OpenTTD/actions/annotation-check@v6
uses: OpenTTD/actions/annotation-check@v7
+2 -2
View File
@@ -18,11 +18,11 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Setup vcpkg
id: vcpkg
uses: OpenTTD/actions/setup-vcpkg@v6
uses: OpenTTD/actions/setup-vcpkg@v7
- name: Install OpenGFX
shell: bash
+6 -5
View File
@@ -25,11 +25,11 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Setup vcpkg
id: vcpkg
uses: OpenTTD/actions/setup-vcpkg@v6
uses: OpenTTD/actions/setup-vcpkg@v7
- name: Install dependencies
run: |
@@ -49,6 +49,7 @@ jobs:
libopus-dev \
libopusfile-dev \
libsdl2-dev \
libsoxr-dev \
zlib1g-dev \
# EOF
@@ -75,7 +76,7 @@ jobs:
echo "::endgroup::"
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
uses: github/codeql-action/init@v4.37.9
with:
languages: cpp
config-file: ./.github/codeql/codeql-config.yml
@@ -91,7 +92,7 @@ jobs:
echo "::endgroup::"
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
uses: github/codeql-action/analyze@v4.37.9
with:
category: /language:cpp
upload: False
@@ -109,6 +110,6 @@ jobs:
output: sarif-results/cpp.sarif
- name: Upload results
uses: github/codeql-action/upload-sarif@v4
uses: github/codeql-action/upload-sarif@v4.37.9
with:
sarif_file: sarif-results/cpp.sarif
+2 -2
View File
@@ -14,12 +14,12 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
fetch-depth: 4
- name: Get pull-request commits
uses: OpenTTD/actions/checkout-pull-request@v6
uses: OpenTTD/actions/checkout-pull-request@v7
- name: Check commits
uses: OpenTTD/OpenTTD-git-hooks@main
+2 -2
View File
@@ -14,12 +14,12 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
fetch-depth: 4
- name: Get pull-request commits
uses: OpenTTD/actions/checkout-pull-request@v6
uses: OpenTTD/actions/checkout-pull-request@v7
- name: Install Doxygen
uses: ./.github/install-doxygen
+2 -2
View File
@@ -14,12 +14,12 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
fetch-depth: 4
- name: Get pull-request commits
uses: OpenTTD/actions/checkout-pull-request@v6
uses: OpenTTD/actions/checkout-pull-request@v7
- name: Check descriptions of source files
run: |
+4 -11
View File
@@ -11,11 +11,11 @@ jobs:
container:
# If you change this version, change the numbers in the cache step,
# .github/workflows/ci-emscripten.yml (2x) and os/emscripten/Dockerfile too.
image: emscripten/emsdk:3.1.57
image: emscripten/emsdk:6.0.1
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha }}
@@ -24,20 +24,13 @@ jobs:
git config --global --add safe.directory ${GITHUB_WORKSPACE}
git checkout -b pr${{ github.event.pull_request.number }}
- name: Update to modern GCC
run: |
apt-get update
apt-get install -y gcc-12 g++-12
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 100
- name: Setup cache
uses: actions/cache@v5
uses: actions/cache@v6
with:
path: /emsdk/upstream/emscripten/cache
# If you change this version, change the numbers in the image configuration step,
# .github/workflows/ci-emscripten.yml (2x) and os/emscripten/Dockerfile too.
key: 3.1.57-${{ runner.os }}
key: 6.0.1-${{ runner.os }}
- name: Add liblzma support
run: |
+1 -1
View File
@@ -41,7 +41,7 @@ jobs:
echo "number=$(cat pr/number)" >> $GITHUB_OUTPUT
- name: Publish preview
uses: cloudflare/wrangler-action@v3
uses: cloudflare/wrangler-action@v4
with:
apiToken: ${{ secrets.PREVIEW_CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.PREVIEW_CLOUDFLARE_ACCOUNT_ID }}
+1 -1
View File
@@ -114,7 +114,7 @@ jobs:
- name: Setup vcpkg
id: vcpkg
uses: OpenTTD/actions/setup-vcpkg@v6
uses: OpenTTD/actions/setup-vcpkg@v7
with:
vcpkg-location: /vcpkg
mono-install-command: 'yum install -y mono-complete'
+1 -1
View File
@@ -39,7 +39,7 @@ jobs:
- name: Setup vcpkg
id: vcpkg
uses: OpenTTD/actions/setup-vcpkg@v6
uses: OpenTTD/actions/setup-vcpkg@v7
- name: Install dependencies
env:
+3 -3
View File
@@ -30,14 +30,14 @@ jobs:
steps:
- name: Checkout (Release)
if: github.event_name == 'release'
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
# We generate a changelog; for this we need the full git log.
fetch-depth: 0
- name: Checkout (Manual)
if: github.event_name == 'workflow_dispatch'
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
ref: ${{ github.event.inputs.ref }}
# We generate a changelog; for this we need the full git log.
@@ -45,7 +45,7 @@ jobs:
- name: Checkout (Trigger)
if: github.event_name == 'repository_dispatch'
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
ref: ${{ github.event.client_payload.ref }}
# We generate a changelog; for this we need the full git log.
+1 -1
View File
@@ -47,7 +47,7 @@ jobs:
- name: Setup vcpkg
id: vcpkg
uses: OpenTTD/actions/setup-vcpkg@v6
uses: OpenTTD/actions/setup-vcpkg@v7
- name: Install dependencies
shell: bash
@@ -14,7 +14,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Check for finding script functions that require company/deity mode enforcement/checks
run: |
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Check for unused strings
run: |
+2 -2
View File
@@ -88,7 +88,7 @@ jobs:
- prepare
name: Publish bundles
uses: OpenTTD/actions/.github/workflows/rw-cdn-upload.yml@v6
uses: OpenTTD/actions/.github/workflows/rw-cdn-upload.yml@v7
secrets:
CDN_SIGNING_KEY: ${{ secrets.CDN_SIGNING_KEY }}
DEPLOYMENT_APP_ID: ${{ secrets.DEPLOYMENT_APP_ID }}
@@ -103,7 +103,7 @@ jobs:
- prepare
name: Publish symbols
uses: OpenTTD/actions/.github/workflows/rw-symbols-upload.yml@v6
uses: OpenTTD/actions/.github/workflows/rw-symbols-upload.yml@v7
secrets:
SYMBOLS_SIGNING_KEY: ${{ secrets.SYMBOLS_SIGNING_KEY }}
with:
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
path: openttd-windows-store
- name: Configure Microsoft Store CLI
uses: microsoft/microsoft-store-apppublisher@v1.3
uses: microsoft/microsoft-store-apppublisher@v1.4
- name: Reconfigure store credentials
run: msstore reconfigure `
+3 -1
View File
@@ -156,6 +156,7 @@ if(NOT OPTION_DEDICATED)
endif()
endif()
find_package(OpusFile)
find_package(Soxr)
endif()
if(APPLE)
enable_language(OBJCXX)
@@ -330,6 +331,7 @@ if(NOT OPTION_DEDICATED)
link_package(ICU_I18N TARGET ICU::i18n)
link_package(ICU_UC TARGET ICU::uc)
link_package(OpusFile TARGET OpusFile::opusfile)
link_package(Soxr TARGET Soxr::soxr)
if(SDL2_FOUND AND OPENGL_FOUND AND UNIX)
# SDL2 dynamically loads OpenGL if needed, so do not link to OpenGL when
@@ -370,7 +372,7 @@ if(EMSCRIPTEN)
add_definitions(-s DISABLE_EXCEPTION_CATCHING=0)
# Export functions to Javascript.
target_link_libraries(WASM::WASM INTERFACE "-s EXPORTED_FUNCTIONS='[\"_main\", \"_em_openttd_add_server\"]' -s EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
target_link_libraries(WASM::WASM INTERFACE "-s EXPORTED_FUNCTIONS='[\"_main\", \"_em_openttd_add_server\"]' -s EXPORTED_RUNTIME_METHODS='[\"cwrap\", \"HEAPU8\"]'")
# Preload all the files we generate during build.
# As we do not compile with FreeType / FontConfig, we also have no way to
+1
View File
@@ -12,6 +12,7 @@ What is simple to some might appear very complicated to others. Documentation he
* Use Foo() instead of Foo(void).
* Prefer using "const" for reference and compound parameters when appropriate.
* If a member function can be a const function, make it so.
* Order of qualifiers is `static inline` / `static constexpr`, don't use `inline` with `constexpr`.
```c++
void ThisIsAFunction()
{
+170 -97
View File
@@ -1,104 +1,177 @@
## 16.x
### 16.0-beta3 (2026-09-19)
- Feature: Double-ended ships (#16002)
- Feature: [Script] AI API to remove rail depot (#15933)
- Feature: Create new folders from the save dialog (#15730)
- Feature: Screensaver Mode (#15350)
- Add: Use LibSoxr for high quality sample-rate conversion (#15924)
- Add: Allow placing/erasing rough terrain in scenario editor (#15624)
- Add: Show train length in reworked vehicle info panel (#15389)
- Add: [NewGRF] Number of nearby stations for towns (#15200)
- Add: [NewGRF] Town additional information (#15198)
- Add: [NewGRF] Nearby tile info for towns (#15194)
- Add: Add water and coastal rock tiles (#15869)
- Add: Place rocks randomly around lighthouses (#15869)
- Change: Allow orders and timetable windows to be smaller (#16008)
- Change: Allow font size to be changed with default truetype font (#16000)
- Change: Allow admin to join any company in all interfaces (#15992)
- Change: Generate rough tiles as clusters, like rocks (#15963)
- Change: [NewGRF] Remove airport tile ID hole at 0xFF (#15956)
- Change: [NewGRF] Remove object ID hole at 0xFF (#15956)
- Change: [NewGRF] Remove industry tile ID hole at 0xFF (#15956)
- Change: Move small map buttons to side of window (#15885)
- Change: Update wording of force unload order (#15880)
- Change: New coast and toyland rock overlay sprites (#15869)
- Change: Lowering tiles when terraforming makes rocky slopes (#15822)
- Change: Limit purchase list rows to 1.5x original design height (#15749)
- Change: Clip content in purchase list to each row (#15749)
- Change: Account for driving cabs in driving backwards conditional order (#15494)
- Change: [NewGRF] Ensure modflags bit 8 respects old behavior when train is driving backwards (#15485)
- Change: Allow road vehicles to overtake through junctions between one-way roads (#15445)
- Change: Use new game setting for disable_elrails when loading very old save (#14481)
- Change: [NewGRF] Remove per-grf industry tile limit (#12183)
- Fix #15824: Game crash when truncating cargo of crashed vehicle (#16005)
- Fix: Reducing a vehicle's cargo capacity incorrectly truncated the cargo. (#16004)
- Fix #15506: [Script] Avoid ternary signed/unsigned conversion when returning literal -1 (#16001)
- Fix #15759: Inconsistency in disabled electric rails compatibility (#15994)
- Fix #15990: Game crash when clearing up crashed train with last wagon in depot (#15991)
- Fix #15985: Incorrect train station area after adding to a station (#15986)
- Fix: Don't require glyphs for non-breaking space characters (#15982)
- Fix #15863: Train should not clear path reservation under the other train that crashed into its front (#15980)
- Fix #15636: Allow shift and ctrl modifiers in hotkeys (#15976)
- Fix: [NewGRF] Validate airport tile layouts (#15970)
- Fix: [NewGRF] Improve industry tile layout validation (#15970)
- Fix: Wrong button size in Bootstrap query window if game window resized (#15968)
- Fix #15233: Don't require glyphs for various whitespace characters (#15967)
- Fix: Wrong category for some base set debug messages (#15965)
- Fix #15961: Don't pass a temporary object to BreakIterator::setText (#15962)
- Fix: Autoclean empty time only checked for connected clients at month boundary (#15954)
- Fix: Invalidate/update vehicle caches when vehicle is marked dirty (#15946)
- Fix: Random company colours choice was reversed (#15944)
- Fix: Properly disallow duplicate company names (#15911)
- Fix #15905: Dual-headed engines showed incorrect capacity when sorting (#15907)
- Fix: Potential off-by-one out of bounds read during saving (#15903)
- Fix: Coast tiles were shown as water tiles in small map (#15883)
- Fix: Limit vehicle reliability to the model's current maximum reliability (#15879)
- Fix: Rail depot overbuild did not handle associated reservation (#15860)
- Fix #15849: Rivers no longer fill small seas with original land gen (#15852)
- Fix: Player-placed house protection for houses should override the callback (#14408)
### 16.0-beta2 (2026-07-12)
- Feature: Allow bridges over depots (#15836)
- Feature: Increase maximum number of vehicles per type to 10,000 (#15810)
- Feature: Add and remove whole classes to picker collections (#15808)
- Feature: Station list can be filtered by name (#15772)
- Change: Use "bridge ... too low" message for bridgeable objects (#15838)
- Fix: Use meaningful tooltips for graph range toggle buttons (#15842)
- Fix #15826: Exclude allow any/all options for AI companies (#15834)
- Fix #7992: Fix for catenary road and tram catenary sprites not being drawn on bridges (#15811)
- Fix #15784: Crash due to incorrect road build toolbar when switching road tram types (#15789)
- Fix: [NewGRF] Make 'signals on traffic side' consistent with explicit settings (#15661)
- Fix: [Win32] Explicitly initialize COM in Win32 video driver (#15553)
### 16.0-beta1 (2026-06-25)
Feature: Add default road and tram selection (#15585)
Feature: Trains with an engine on the rear can drive backwards when reversing (#15379)
Feature: Add worldgen setting for average height of terrain (#14989)
Feature: Add text filter to dropdown lists (#14842)
Feature: User-defined collections of saved items in the picker window (#14813)
Feature: Configurable sign text colors in scenario editor (#14743)
Feature: Allow placing an area of 1x1 houses in scenario editor (#14708)
Feature: Scale cargo payment aging rate (#14635)
Feature: Support automatic detection of data from Atari's Transport Tycoon Deluxe re-release (#15483)
Add: [NewGRF] Implement custom waypoint layouts by callback 24 (#15616)
Add: List 'Place object' in landscaping dropdown (#15609)
Add: Setting to disable aircraft range limit (#15433)
Add: Show maximum reliability in vehicle info (#15401)
Add: Lower the Send To Depot button when a vehicle is on its way to one (#15397)
Add: Setting to disallow train magic flip, and reverse at reduced speed (#15391)
Add: [NewGRF] Variable for when a train is driving backwards (#15379)
Add: [NewGRF] Flag to allow unpowered wagon to lead train when backing up (#15379)
Add: [NewGRF] Station flag to divide cargo by area instead of perimeter (#15253)
Add: Company allow-list can be set to allow anyone (#15204)
Add: Record history of cargo delivered to towns (#15184)
Add: Show additional vehicle details based on sort criteria (#15158)
Add: Setting to control minimum distance between towns (#14893)
Change: Selecting Rail/Roadtype updates build toolbar instead of closing and reopening (#15589)
Change: Default setting to review orders excludes stopped vehicles (#15565)
Change: Most used rail type takes ownership into account (#15489)
Change: Test font for eligibility before adding as fallback (#15412)
Change: Clarify max age shown in vehicle info window (#15403)
Change: Show "Delete All" in order window delete button when applicable (#15370)
Change: Make continuation error messages consistent (#15328)
Change: Distinguish between 'Flat land required' and 'Land sloped in wrong direction' for building depots (#15327)
Change: Allow subsidies with CargoDist (#15189)
Change: Removing river tiles reduces local authority rating (#15180)
Change: Protect rivers from removal when terraforming (#15176)
Change: [Script] Reformat callstack output (#15171)
Change: Apply slightly more padding to image-text buttons (#15077)
Change: [NewGRF] Display rail and road type speed limit text in yellow (#15076)
Change: Make smallmap show infinite water, if enabled (#15041)
Change: Add support for next/previous/first/last rail/road/tram type hotkeys (#15028)
Change: Allow rocks on desert tiles (#14979)
Change: [Script] Include Array/PriorityQueye/ScriptList contents in script memory allocation total (#14954)
Change: [Script] Various ScriptList methods are now suspendable (#14943, #14762)
Change: Improve generation of coasts at map edges (#14868)
Change: Show only selected badge in badge filter dropdown buttons (#14855)
Change: River springs must be surrounded by hills (#14845)
Change: Vehicles loading at stations don't lose reliability (#14841)
Change: Generate lighthouses along coasts and near towns (#14828)
Change: Transmitter object only spawns after original base year (#14786)
Change: Share one window for engine preview pop ups (#14703)
Fix: [NewGRF] Town name language incorrectly decoded (#15691)
Fix #15606: Undefined behaviour may cause buttons to be invisible (#15686)
Fix #14975: Show correct tile for tunnel error message (#15660)
Fix: [NewGRF] Incorrect language IDs passed to TranslateTTDPatchCodes (#15655)
Fix: Scenario editor random industry generation (#15626)
Fix: [NewGRF] Ignore blocked waypoint tiles (#15620)
Fix: [NewGRF] Pylons and no-wires flags were ignored for waypoint tiles (#15619)
Fix: Dedicated server signal handling for SIGTERM/SIGINT/SIGQUIT (#15607)
Fix: [NewGRF] Potential out-of-bounds read when performing GRM (#15600)
Fix: Badge offsets not ignored when determining width (#15588)
Fix: Account for NewGRF's global train width when drawing dual-head engines (#15587)
Fix: Station list facility buttons do not produce click sound (#15569)
Fix #15495: Fix incorrectly built default waypoints (#15562)
Fix #15495: Unable to build bridge over default waypoints (#15562)
Fix #15235: Make GameScripts obey town road construction setting (#15559)
Fix: Crash when loading crash save with no viewport coordinates (#15550)
Fix #15520: Fix viewport snap back on stop following vehicle (#15520) (#15531)
Fix: Buttons for choosing engine in preview window show for single engine (#15514)
Fix #15511: Vehicle passed to commands must be a company buildable type (#15512)
Fix #15497: [Script] ScriptController::Break not pausing in TestMode (#15498)
Fix: Coordinate transformation for JSON town placement when anticlockwise (#15490)
Fix: NewGRF debug handler for towns in wrong place since badges (#15467)
Fix: Object id overrides were not reset between games (#15465)
Fix: Debug saveload errors were clobbered (#15452)
Fix: Refresh client list when client renames (#15439)
Fix #15428: [Fluidsynth] Treat configured synth.gain as maximum instead of hardcoded value (#15429)
Fix: Refresh string width cache for all loaded fonts (#15427)
Fix: Typo in Hungarian town name suffix ("kak" -> "lak") (#15421)
Fix: [NewGRF] Variable 0x69 has not been added for waypoints (#15396)
Fix: Dropdown text filter could interfere with hotkeys after closing (#15395)
Fix: Rejecting or accepting engine preview incorrectly closed preview window (#15378)
Fix #15318: Nonsensical error message when trying to send aircraft to hangar with no usable airports (#15334)
Fix #15234: Null pointer dereference opening sign edit window when sign 0 does not exist (#15236)
Fix: [GS] Docs are missing or do not match the code (#15230)
Fix: Off by one and redundant logic in snowy road checks (#15214)
Fix #15137: Roads built on steep slopes at the minimum snow level height have inconsistent snowiness (#15190)
Fix: Station view window fold/unfold not refreshing scrollbar (#15187)
Fix: Use consistent description for invalid orders (#15177)
Fix: [Script] Give GetPrimary/SecondaryLiveryColour preconditions (#15169)
Fix: Cocoa video driver did not register (#15145)
Fix: MacOS version detection was broken (#15145)
Fix #13600: Make terraform click+draggable in scenario editor (#15135)
Fix: [Script] Map some error strings to existing errors (#15113)
Fix: Allow to build buoys at (0x0) (#14983)
Fix #14610: Do not treat aircraft with only depot orders as having valid orders (#14961)
Fix #12937: Allow the computer to go to sleep while the game is paused (#14948)
Fix: Company query popups do not update in multiplayer (#14947)
Fix #14892: Potential crash when logging fonts for survey (#14896)
Fix #14827: Store random trigger information per-tile (#14830)
- Feature: Add default road and tram selection (#15585)
- Feature: Trains with an engine on the rear can drive backwards when reversing (#15379)
- Feature: Add worldgen setting for average height of terrain (#14989)
- Feature: Add text filter to dropdown lists (#14842)
- Feature: User-defined collections of saved items in the picker window (#14813)
- Feature: Configurable sign text colors in scenario editor (#14743)
- Feature: Allow placing an area of 1x1 houses in scenario editor (#14708)
- Feature: Scale cargo payment aging rate (#14635)
- Feature: Support automatic detection of data from Atari's Transport Tycoon Deluxe re-release (#15483)
- Add: [NewGRF] Implement custom waypoint layouts by callback 24 (#15616)
- Add: List 'Place object' in landscaping dropdown (#15609)
- Add: Setting to disable aircraft range limit (#15433)
- Add: Show maximum reliability in vehicle info (#15401)
- Add: Lower the Send To Depot button when a vehicle is on its way to one (#15397)
- Add: Setting to disallow train magic flip, and reverse at reduced speed (#15391)
- Add: [NewGRF] Variable for when a train is driving backwards (#15379)
- Add: [NewGRF] Flag to allow unpowered wagon to lead train when backing up (#15379)
- Add: [NewGRF] Station flag to divide cargo by area instead of perimeter (#15253)
- Add: Company allow-list can be set to allow anyone (#15204)
- Add: Record history of cargo delivered to towns (#15184)
- Add: Show additional vehicle details based on sort criteria (#15158)
- Add: Setting to control minimum distance between towns (#14893)
- Change: Selecting Rail/Roadtype updates build toolbar instead of closing and reopening (#15589)
- Change: Default setting to review orders excludes stopped vehicles (#15565)
- Change: Most used rail type takes ownership into account (#15489)
- Change: Test font for eligibility before adding as fallback (#15412)
- Change: Clarify max age shown in vehicle info window (#15403)
- Change: Show "Delete All" in order window delete button when applicable (#15370)
- Change: Make continuation error messages consistent (#15328)
- Change: Distinguish between 'Flat land required' and 'Land sloped in wrong direction' for building depots (#15327)
- Change: Allow subsidies with CargoDist (#15189)
- Change: Removing river tiles reduces local authority rating (#15180)
- Change: Protect rivers from removal when terraforming (#15176)
- Change: [Script] Reformat callstack output (#15171)
- Change: Apply slightly more padding to image-text buttons (#15077)
- Change: [NewGRF] Display rail and road type speed limit text in yellow (#15076)
- Change: Make smallmap show infinite water, if enabled (#15041)
- Change: Add support for next/previous/first/last rail/road/tram type hotkeys (#15028)
- Change: Allow rocks on desert tiles (#14979)
- Change: [Script] Include Array/PriorityQueye/ScriptList contents in script memory allocation total (#14954)
- Change: [Script] Various ScriptList methods are now suspendable (#14943, #14762)
- Change: Improve generation of coasts at map edges (#14868)
- Change: Show only selected badge in badge filter dropdown buttons (#14855)
- Change: River springs must be surrounded by hills (#14845)
- Change: Vehicles loading at stations don't lose reliability (#14841)
- Change: Generate lighthouses along coasts and near towns (#14828)
- Change: Transmitter object only spawns after original base year (#14786)
- Change: Share one window for engine preview pop ups (#14703)
- Fix: [NewGRF] Town name language incorrectly decoded (#15691)
- Fix #15606: Undefined behaviour may cause buttons to be invisible (#15686)
- Fix #14975: Show correct tile for tunnel error message (#15660)
- Fix: [NewGRF] Incorrect language IDs passed to TranslateTTDPatchCodes (#15655)
- Fix: Scenario editor random industry generation (#15626)
- Fix: [NewGRF] Ignore blocked waypoint tiles (#15620)
- Fix: [NewGRF] Pylons and no-wires flags were ignored for waypoint tiles (#15619)
- Fix: Dedicated server signal handling for SIGTERM/SIGINT/SIGQUIT (#15607)
- Fix: [NewGRF] Potential out-of-bounds read when performing GRM (#15600)
- Fix: Badge offsets not ignored when determining width (#15588)
- Fix: Account for NewGRF's global train width when drawing dual-head engines (#15587)
- Fix: Station list facility buttons do not produce click sound (#15569)
- Fix #15495: Fix incorrectly built default waypoints (#15562)
- Fix #15495: Unable to build bridge over default waypoints (#15562)
- Fix #15235: Make GameScripts obey town road construction setting (#15559)
- Fix: Crash when loading crash save with no viewport coordinates (#15550)
- Fix #15520: Fix viewport snap back on stop following vehicle (#15520) (#15531)
- Fix: Buttons for choosing engine in preview window show for single engine (#15514)
- Fix #15511: Vehicle passed to commands must be a company buildable type (#15512)
- Fix #15497: [Script] ScriptController::Break not pausing in TestMode (#15498)
- Fix: Coordinate transformation for JSON town placement when anticlockwise (#15490)
- Fix: NewGRF debug handler for towns in wrong place since badges (#15467)
- Fix: Object id overrides were not reset between games (#15465)
- Fix: Debug saveload errors were clobbered (#15452)
- Fix: Refresh client list when client renames (#15439)
- Fix #15428: [Fluidsynth] Treat configured synth.gain as maximum instead of hardcoded value (#15429)
- Fix: Refresh string width cache for all loaded fonts (#15427)
- Fix: Typo in Hungarian town name suffix ("kak" -> "lak") (#15421)
- Fix: [NewGRF] Variable 0x69 has not been added for waypoints (#15396)
- Fix: Dropdown text filter could interfere with hotkeys after closing (#15395)
- Fix: Rejecting or accepting engine preview incorrectly closed preview window (#15378)
- Fix #15318: Nonsensical error message when trying to send aircraft to hangar with no usable airports (#15334)
- Fix #15234: Null pointer dereference opening sign edit window when sign 0 does not exist (#15236)
- Fix: [GS] Docs are missing or do not match the code (#15230)
- Fix: Off by one and redundant logic in snowy road checks (#15214)
- Fix #15137: Roads built on steep slopes at the minimum snow level height have inconsistent snowiness (#15190)
- Fix: Station view window fold/unfold not refreshing scrollbar (#15187)
- Fix: Use consistent description for invalid orders (#15177)
- Fix: [Script] Give GetPrimary/SecondaryLiveryColour preconditions (#15169)
- Fix: Cocoa video driver did not register (#15145)
- Fix: MacOS version detection was broken (#15145)
- Fix #13600: Make terraform click+draggable in scenario editor (#15135)
- Fix: [Script] Map some error strings to existing errors (#15113)
- Fix: Allow to build buoys at (0x0) (#14983)
- Fix #14610: Do not treat aircraft with only depot orders as having valid orders (#14961)
- Fix #12937: Allow the computer to go to sleep while the game is paused (#14948)
- Fix: Company query popups do not update in multiplayer (#14947)
- Fix #14892: Potential crash when logging fonts for survey (#14896)
- Fix #14827: Store random trigger information per-tile (#14830)
## 15.x
-20
View File
@@ -56,11 +56,6 @@ macro(compile_flags)
# This flag disables the broken optimisation to work around the bug
add_compile_options(/d2ssa-rse-)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
add_compile_options(
-Wno-multichar
)
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
add_compile_options(
-W
@@ -78,9 +73,6 @@ macro(compile_flags)
-Wnon-virtual-dtor
-Wsuggest-override
# We use 'ABCD' multichar for SaveLoad chunks identifiers
-Wno-multichar
# Prevent optimisation supposing enums are in a range specified by the standard
# For details, see http://gcc.gnu.org/PR43680 and PR#5246.
-fno-strict-enums
@@ -126,18 +118,6 @@ macro(compile_flags)
endif()
endif()
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
add_compile_options(
-Wall
# warning #873: function ... ::operator new ... has no corresponding operator delete ...
-wd873
# warning #1292: unknown attribute "fallthrough"
-wd1292
# warning #1899: multicharacter character literal (potential portability problem)
-wd1899
# warning #2160: anonymous union qualifier is ignored
-wd2160
)
else()
message(FATAL_ERROR "No warning flags are set for this compiler yet; please consider creating a Pull Request to add support for this compiler.")
endif()
+41
View File
@@ -0,0 +1,41 @@
include(FindPackageHandleStandardArgs)
find_library(Soxr_LIBRARY
NAMES soxr
)
include(FixVcpkgLibrary)
FixVcpkgLibrary(Soxr)
set(Soxr_COMPILE_OPTIONS "" CACHE STRING "Extra compile options of soxr")
set(Soxr_LINK_LIBRARIES "" CACHE STRING "Extra link libraries of soxr")
set(Soxr_LINK_FLAGS "" CACHE STRING "Extra link flags of soxr")
find_path(Soxr_INCLUDE_PATH
NAMES soxr.h
)
find_package_handle_standard_args(Soxr
REQUIRED_VARS Soxr_LIBRARY Soxr_INCLUDE_PATH
)
if(Soxr_FOUND)
if(NOT TARGET Soxr::soxr)
add_library(Soxr::soxr UNKNOWN IMPORTED)
set_target_properties(Soxr::soxr PROPERTIES
IMPORTED_LOCATION "${Soxr_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${Soxr_INCLUDE_PATH}"
INTERFACE_COMPILE_OPTIONS "${Soxr_COMPILE_OPTIONS}"
INTERFACE_LINK_LIBRARIES "${Soxr_LINK_LIBRARIES}"
INTERFACE_LINK_FLAGS "${Soxr_LINK_FLAGS}"
)
FixVcpkgTarget(Soxr Soxr::soxr)
# Prevent undefined references in UCRT64 MinGW environment
if(MINGW AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set_property(TARGET Soxr::soxr APPEND PROPERTY INTERFACE_LINK_LIBRARIES gomp)
endif()
endif()
endif()
+15 -6
View File
@@ -191,17 +191,26 @@ elseif(UNIX)
set(PLATFORM "unknown")
else()
if(EXISTS "/etc/os-release")
file(STRINGS "/etc/os-release" OS_RELEASE_CONTENTS REGEX "^ID=")
string(REGEX MATCH "ID=(.*)" _ ${OS_RELEASE_CONTENTS})
set(DISTRO_ID ${CMAKE_MATCH_1})
if(DISTRO_ID STREQUAL "arch")
file(STRINGS "/etc/os-release" OS_RELEASE_LIKE_CONTENTS REGEX "^ID_LIKE=")
if (OS_RELEASE_LIKE_CONTENTS)
string(REGEX MATCH "ID_LIKE=\\\"?([^\\\"]+)" _ ${OS_RELEASE_LIKE_CONTENTS})
string(REGEX MATCHALL "([^ ]+)" DISTRO_LIKE_IDS ${CMAKE_MATCH_1})
endif()
if (DISTRO_LIKE_IDS)
set(DISTRO_IDS ${DISTRO_LIKE_IDS})
else()
file(STRINGS "/etc/os-release" OS_RELEASE_CONTENTS REGEX "^ID=")
string(REGEX MATCH "ID=(.*)" _ ${OS_RELEASE_CONTENTS})
set(DISTRO_IDS ${CMAKE_MATCH_1})
endif()
if("arch" IN_LIST DISTRO_IDS)
set(PLATFORM "arch")
set(CPACK_GENERATOR "TXZ")
elseif(DISTRO_ID STREQUAL "fedora" OR DISTRO_ID STREQUAL "rhel")
elseif("fedora" IN_LIST DISTRO_IDS OR "rhel" IN_LIST DISTRO_IDS)
set(PLATFORM "fedora")
set(CPACK_GENERATOR "RPM")
include(PackageRPM)
elseif(DISTRO_ID STREQUAL "ubuntu" OR DISTRO_ID STREQUAL "debian" OR DISTRO_ID STREQUAL "linuxmint")
elseif("debian" IN_LIST DISTRO_IDS OR "ubuntu" IN_LIST DISTRO_IDS OR "linuxmint" IN_LIST DISTRO_IDS)
file(STRINGS "/etc/os-release" OS_RELEASE_CODENAME REGEX "^VERSION_CODENAME=")
string(REGEX MATCH "VERSION_CODENAME=(.*)" _ ${OS_RELEASE_CODENAME})
set(RELEASE_CODENAME ${CMAKE_MATCH_1})
+1 -1
View File
@@ -726,7 +726,7 @@
</ul>
</li>
<li>m3 bit 6 : free</li>
<li>m3 bit 5 : The house is protected from the town upgrading it</li>
<li>m3 bit 5 : The house is protected by the player from the town upgrading it</li>
<li>m3 bits 4..0 : triggers activated <a href="#newhouses">(newhouses)</a></li>
<li>m4 : free</li>
<li>m5 : see m3 bit 7</li>
+2 -2
View File
@@ -156,7 +156,7 @@ the array so you can quickly see what is used and what is not.
<td class="caption">finished house</td>
<td class="bits" rowspan=2><span class="used" title="House random bits">XXXX XXXX</span></td>
<td class="bits" rowspan=2><span class="pool" title="Town index on pool">XXXX XXXX XXXX XXXX</span></td>
<td class="bits"><span class="used" title="House is complete/in construction (see m5)">1</span><span class="free">O</span><span class="used" title="The house is protected from the town upgrading it.">X</span><span class="usable" title="Activated triggers (bits 2..4 don't have a meaning)">X XX</span><span class="used" title="Activated triggers (bits 2..4 don't have a meaning)">XX</span></td>
<td class="bits"><span class="used" title="House is complete/in construction (see m5)">1</span><span class="free">O</span><span class="used" title="The house is protected by the player from the town upgrading it.">X</span><span class="usable" title="Activated triggers (bits 2..4 don't have a meaning)">X XX</span><span class="used" title="Activated triggers (bits 2..4 don't have a meaning)">XX</span></td>
<td class="bits" rowspan=2><span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="used" title="Age in years, clamped at 255">XXXX XXXX</span></td>
<td class="bits" rowspan=2><span class="abuse" title="Newhouses activated: periodic processing time remaining; if not, lift position for houses 04 and 05">XXXX XX</span><span class="used" title="Animated tile state">XX</span></td>
@@ -165,7 +165,7 @@ the array so you can quickly see what is used and what is not.
</tr>
<tr>
<td class="caption">house under construction</td>
<td class="bits"><span class="used" title="House is complete/in construction (see m5)">O</span><span class="free">O</span><span class="used" title="The house is protected from the town upgrading it.">X</span><span class="usable" title="Activated triggers (bits 2..4 don't have a meaning)">X XX</span><span class="used" title="Activated triggers (bits 2..4 don't have a meaning)">XX</span></td>
<td class="bits"><span class="used" title="House is complete/in construction (see m5)">O</span><span class="free">O</span><span class="used" title="The house is protected by the player from the town upgrading it.">X</span><span class="usable" title="Activated triggers (bits 2..4 don't have a meaning)">X XX</span><span class="used" title="Activated triggers (bits 2..4 don't have a meaning)">XX</span></td>
<td class="bits"><span class="free">OOO</span><span class="used" title="Construction stage">X X</span><span class="used" title="Construction counter">XXX</span></td>
</tr>
<tr>
+16 -16
View File
@@ -69,19 +69,19 @@ An example of a valid tag is `PLYR` when looking at it via ASCII, which contains
`[4..4]` - Next follows a byte where the lower 4 bits contain the type.
The possible valid types are:
- `0` - `CH_RIFF` - This chunk is a binary blob.
- `1` - `CH_ARRAY` - This chunk is a list of items.
- `2` - `CH_SPARSE_ARRAY` - This chunk is a list of items.
- `3` - `CH_TABLE` - This chunk is self-describing list of items.
- `4` - `CH_SPARSE_TABLE` - This chunk is self-describing list of items.
- `0` - `ChunkType::Riff` - This chunk is a binary blob.
- `1` - `ChunkType::Array` - This chunk is a list of items.
- `2` - `ChunkType::SparseArray` - This chunk is a list of items.
- `3` - `ChunkType::Table` - This chunk is self-describing list of items.
- `4` - `ChunkType::SparseTable` - This chunk is self-describing list of items.
Now per type the format is (slightly) different.
### CH_RIFF
### ChunkType::Riff
(since savegame version 295, this chunk type is only used for MAP-chunks, containing bit-information about each tile on the map)
A `CH_RIFF` starts with an `uint24` which together with the upper-bits of the type defines the length of the chunk.
A `ChunkType::Riff` starts with an `uint24` which together with the upper-bits of the type defines the length of the chunk.
In pseudo-code:
```
@@ -94,11 +94,11 @@ if type == 0
The next `length` bytes are part of the chunk.
What those bytes mean depends on the tag of the chunk; further details per chunk can be found in the source-code.
### CH_ARRAY / CH_SPARSE_ARRAY
### ChunkType::Array / ChunkType::SparseArray
(this chunk type is deprecated since savegame version 295 and is no longer in use)
`[0..G1]` - A `CH_ARRAY` / `CH_SPARSE_ARRAY` starts with a `gamma`, indicating the size of the next item plus one.
`[0..G1]` - A `ChunkType::Array` / `ChunkType::SparseArray` starts with a `gamma`, indicating the size of the next item plus one.
If this size value is zero, it indicates the end of the list.
This indicates the full length of the next item minus one.
In psuedo-code:
@@ -111,21 +111,21 @@ loop
read <size> bytes
```
`[]` - For `CH_ARRAY` there is an implicit index.
`[]` - For `ChunkType::Array` there is an implicit index.
The loop starts at zero, and every iteration adds one to the index.
For entries in the game that were not allocated, the `size` will be zero.
`[G1+1..G2]` - For `CH_SPARSE_ARRAY` there is an explicit index.
`[G1+1..G2]` - For `ChunkType::SparseArray` there is an explicit index.
The `gamma` following the size indicates the index.
The content of the item is a binary blob, and similar to `CH_RIFF`, it depends on the tag of the chunk what it means.
The content of the item is a binary blob, and similar to `ChunkType::Riff`, it depends on the tag of the chunk what it means.
Please check the source-code for further details.
### CH_TABLE / CH_SPARSE_TABLE
### ChunkType::Table / ChunkType::SparseTable
(this chunk type only exists since savegame version 295)
Both `CH_TABLE` and `CH_SPARSE_TABLE` are very similar to `CH_ARRAY` / `CH_SPARSE_ARRAY` respectively.
Both `ChunkType::Table` and `ChunkType::SparseTable` are very similar to `ChunkType::Array` / `ChunkType::SparseArray` respectively.
The only change is that the chunk starts with a header.
This header describes the chunk in details; with the header you know the meaning of each byte in the binary blob that follows.
@@ -168,7 +168,7 @@ struct | substruct3
The headers will be, in order: `table`, `substruct1`, `substruct3`, `substruct2`, each ending with a `type` is zero field.
After reading all the fields of all the headers, there is a list of records.
To read this, see `CH_ARRAY` / `CH_SPARSE_ARRAY` for details.
To read this, see `ChunkType::Array` / `ChunkType::SparseArray` for details.
As each `type` has a well defined length, you can read the records even without knowing anything about the chunk-tag yourself.
@@ -187,7 +187,7 @@ The prefix is strongly advised to avoid conflicts with future-settings in an unp
## Scripts custom data format
Script chunks (`AIPL` and `GSDT`) use `CH_TABLE` chunk type.
Script chunks (`AIPL` and `GSDT`) use `ChunkType::Table` chunk type.
At the end of each record there's an `uint8` to indicate if there's custom data (1) or not (0).
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
c56aad31380c077d619e124bd87c8270
b198439be549299b877e97ca3b58aef1
+3
View File
@@ -51,6 +51,9 @@ if(GRFCODEC_FOUND)
${CMAKE_CURRENT_SOURCE_DIR}/overlay_snowy_rocks_2.png
${CMAKE_CURRENT_SOURCE_DIR}/overlay_snowy_rocks_3.png
${CMAKE_CURRENT_SOURCE_DIR}/overlay_snowy_rocks_4.png
${CMAKE_CURRENT_SOURCE_DIR}/overlay_coastal_rocks.png
${CMAKE_CURRENT_SOURCE_DIR}/overlay_toyland_rocks.png
${CMAKE_CURRENT_SOURCE_DIR}/overlay_toyland_coastal_rocks.png
${CMAKE_CURRENT_SOURCE_DIR}/roadstops.png
${CMAKE_CURRENT_SOURCE_DIR}/road_waypoints.png
${CMAKE_CURRENT_SOURCE_DIR}/signals.png
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+70 -1
View File
@@ -4,7 +4,8 @@
// See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
//
-1 * 0 0C "Overlay rocks"
-1 * 3 05 1A 5F
-1 * 0 07 83 01 \7= 03 73
-1 * 3 05 1A 72
// Plain overlay rocks (unused...)
-1 sprites/overlay_rocks.png 8bpp 1 1 64 31 -31 0 normal
@@ -110,3 +111,71 @@
-1 sprites/overlay_snowy_rocks_4.png 8bpp 1281 1 64 15 -31 0 normal
-1 sprites/overlay_snowy_rocks_4.png 8bpp 1361 1 64 31 -31 -8 normal
-1 sprites/overlay_snowy_rocks_4.png 8bpp 1441 1 64 31 -31 -8 normal
// Coastal rocks
-1 sprites/overlay_coastal_rocks.png 8bpp 1 1 64 31 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 81 1 64 31 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 161 1 64 23 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 241 1 64 23 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 321 1 64 31 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 401 1 64 31 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 481 1 64 23 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 561 1 64 23 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 641 1 64 39 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 721 1 64 39 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 801 1 64 31 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 881 1 64 31 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 961 1 64 39 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 1041 1 64 39 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 1121 1 64 31 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 1201 1 64 47 -31 -16 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 1281 1 64 15 -31 0 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 1361 1 64 31 -31 -8 normal
-1 sprites/overlay_coastal_rocks.png 8bpp 1441 1 64 31 -31 -8 normal
-1 * 6 07 83 01 \7! 03 28
-1 * 3 05 1A 13
// Toyland rocks
-1 sprites/overlay_toyland_rocks.png 8bpp 1 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 81 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 161 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 241 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 321 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 401 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 481 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 561 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 641 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 721 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 801 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 881 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 961 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 1041 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 1121 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 1201 1 64 47 -31 -16 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 1281 1 64 15 -31 0 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 1361 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_rocks.png 8bpp 1441 1 64 31 -31 -8 normal
-1 * 3 05 9A 13 5F
// Toyland coastal rocks
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 1 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 81 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 161 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 241 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 321 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 401 1 64 31 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 481 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 561 1 64 23 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 641 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 721 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 801 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 881 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 961 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 1041 1 64 39 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 1121 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 1201 1 64 47 -31 -16 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 1281 1 64 15 -31 0 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 1361 1 64 31 -31 -8 normal
-1 sprites/overlay_toyland_coastal_rocks.png 8bpp 1441 1 64 31 -31 -8 normal
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

+1 -4
View File
@@ -1,11 +1,8 @@
# If you change this version, change the numbers in .github/workflows/ci-emscripten.yml (2x)
# and .github/workflows/preview-build.yml (2x) too.
FROM emscripten/emsdk:3.1.57
FROM emscripten/emsdk:6.0.1
RUN apt-get update \
&& apt-get install -y gcc-12 g++-12 \
&& update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100 \
&& update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 100 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
+91 -7
View File
@@ -227,7 +227,7 @@ function Regression::Airport()
print(" GetAirportNumHelipads(" + i + "): " + AIAirport.GetAirportNumHelipads(i));
}
print(" GetBankBalance(): " + AICompany.GetBankBalance(AICompany.COMPANY_SELF));
local accounting = AIAccounting();
print(" GetPrice(): " + AIAirport.GetPrice(0));
print(" BuildAirport(): " + AIAirport.BuildAirport(32116, 0, AIStation.STATION_JOIN_ADJACENT));
print(" IsHangarTile(): " + AIAirport.IsHangarTile(32116));
@@ -237,12 +237,13 @@ function Regression::Airport()
print(" IsHangarTile(): " + AIAirport.IsHangarTile(32119));
print(" IsAirportTile(): " + AIAirport.IsAirportTile(32119));
print(" GetAirportType(): " + AIAirport.GetAirportType(32119));
print(" GetBankBalance(): " + AICompany.GetBankBalance(AICompany.COMPANY_SELF));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" RemoveAirport(): " + AIAirport.RemoveAirport(32118));
print(" IsHangarTile(): " + AIAirport.IsHangarTile(32119));
print(" IsAirportTile(): " + AIAirport.IsAirportTile(32119));
print(" GetBankBalance(): " + AICompany.GetBankBalance(AICompany.COMPANY_SELF));
print(" GetCosts(): " + accounting.GetCosts());
print(" BuildAirport(): " + AIAirport.BuildAirport(32116, 0, AIStation.STATION_JOIN_ADJACENT));
}
@@ -1167,7 +1168,7 @@ function Regression::Marine()
print(" IsLockTile(): " + AIMarine.IsLockTile(32116));
print(" IsCanalTile(): " + AIMarine.IsCanalTile(32116));
print(" GetBankBalance(): " + AICompany.GetBankBalance(AICompany.COMPANY_SELF));
local accounting = AIAccounting();
print(" BuildWaterDepot(): " + AIMarine.BuildWaterDepot(28479, 28478));
print(" BuildDock(): " + AIMarine.BuildDock(29253, AIStation.STATION_JOIN_ADJACENT));
print(" BuildBuoy(): " + AIMarine.BuildBuoy(28481));
@@ -1180,7 +1181,7 @@ function Regression::Marine()
print(" IsBuoyTile(): " + AIMarine.IsBuoyTile(28481));
print(" IsLockTile(): " + AIMarine.IsLockTile(28487));
print(" IsCanalTile(): " + AIMarine.IsCanalTile(32127));
print(" GetBankBalance(): " + AICompany.GetBankBalance(AICompany.COMPANY_SELF));
print(" GetCosts(): " + accounting.GetCosts());
local list = AIWaypointList(AIWaypoint.WAYPOINT_BUOY);
print("");
@@ -1196,6 +1197,7 @@ function Regression::Marine()
}
print("");
accounting.ResetCosts();
print(" RemoveWaterDepot(): " + AIMarine.RemoveWaterDepot(28479));
print(" RemoveDock(): " + AIMarine.RemoveDock(29253));
print(" RemoveBuoy(): " + AIMarine.RemoveBuoy(28481));
@@ -1206,7 +1208,7 @@ function Regression::Marine()
print(" IsBuoyTile(): " + AIMarine.IsBuoyTile(28481));
print(" IsLockTile(): " + AIMarine.IsLockTile(28487));
print(" IsCanalTile(): " + AIMarine.IsCanalTile(32127));
print(" GetBankBalance(): " + AICompany.GetBankBalance(AICompany.COMPANY_SELF));
print(" GetCosts(): " + accounting.GetCosts());
print(" BuildWaterDepot(): " + AIMarine.BuildWaterDepot(28479, 28480));
print(" BuildDock(): " + AIMarine.BuildDock(29253, AIStation.STATION_JOIN_ADJACENT));
@@ -1220,6 +1222,7 @@ function Regression::Order()
print("");
print("--Order--");
print(" GetOrderCount(): " + AIOrder.GetOrderCount(12));
print(" GetOrderCount(): " + AIOrder.GetOrderCount(9999));
print(" GetOrderDestination(): " + AIOrder.GetOrderDestination(12, 1));
print(" AreOrderFlagsValid(): " + AIOrder.AreOrderFlagsValid(33416, AIOrder.OF_TRANSFER));
print(" AreOrderFlagsValid(): " + AIOrder.AreOrderFlagsValid(33416, AIOrder.OF_TRANSFER | AIOrder.OF_UNLOAD));
@@ -1396,6 +1399,9 @@ function Regression::Rail()
print(" Depot");
print(" IsRailTile(): " + AIRail.IsRailTile(33411));
print(" BuildRailDepot(): " + AIRail.BuildRailDepot(0, 1));
print(" RemoveRailDepot(): " + AIRail.RemoveRailDepot(33411));
print(" BuildRailDepot(): " + AIRail.BuildRailDepot(33411, 33412));
print(" RemoveRailDepot(): " + AIRail.RemoveRailDepot(33411));
print(" BuildRailDepot(): " + AIRail.BuildRailDepot(33411, 33411));
print(" BuildRailDepot(): " + AIRail.BuildRailDepot(33411, 33410));
print(" BuildRailDepot(): " + AIRail.BuildRailDepot(33411, 33414));
@@ -2105,11 +2111,14 @@ function Regression::Vehicle()
print(" GetWagonAge(): " + AIVehicle.GetWagonAge(17, 2));
print(" GetWagonEngineType(): " + AIVehicle.GetWagonEngineType(17 3));
print(" GetWagonAge(): " + AIVehicle.GetWagonAge(17, 3));
print(" GetVehicleType(): " + AIVehicle.GetVehicleType(14));
print(" GetLength(): " + AIVehicle.GetLength(14));
print(" --Refit--");
print(" GetBuildWithRefitCapacity(): " + AIVehicle.GetBuildWithRefitCapacity(28479, 211, 255));
print(" GetBuildWithRefitCapacity(): " + AIVehicle.GetBuildWithRefitCapacity(28479, 211, 0));
print(" GetBuildWithRefitCapacity(): " + AIVehicle.GetBuildWithRefitCapacity(28479, 211, 9));
print(" GetBuildWithRefitCapacity(): " + AIVehicle.GetBuildWithRefitCapacity(28481, 211, 0));
print(" BuildVehicleWithRefit(): " + AIVehicle.BuildVehicleWithRefit(28479, 211, 9));
print(" GetCapacity(): " + AIVehicle.GetCapacity(20, 9));
print(" GetCapacity(): " + AIVehicle.GetCapacity(20, 5));
@@ -2300,6 +2309,81 @@ function Regression::PriorityQueue()
print(" Count(): " + queue.Count());
}
function Regression::Terraforming()
{
local accounting = AIAccounting();
print("");
print("--Terraforming--");
print(" DemolishTile(): " + AITile.DemolishTile(4033));
print(" DemolishTile(): " + AITile.DemolishTile(60766));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" LowerTile(): " + AITile.LowerTile(8205, AITile.SLOPE_ENW));
print(" RaiseTile(): " + AITile.RaiseTile(8205, AITile.SLOPE_ENW));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" LowerTile(): " + AITile.LowerTile(8205, AITile.SLOPE_ENW));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" LowerTile(): " + AITile.LowerTile(4113, AITile.SLOPE_SW));
print(" RaiseTile(): " + AITile.RaiseTile(5902, AITile.SLOPE_NE));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" RaiseTile(): " + AITile.RaiseTile(7958, AITile.SLOPE_SE));
print(" LowerTile(): " + AITile.LowerTile(7958, AITile.SLOPE_NE));
print(" LowerTile(): " + AITile.LowerTile(7958, AITile.SLOPE_SE));
print(" RaiseTile(): " + AITile.RaiseTile(7958, AITile.SLOPE_SE));
print(" LowerTile(): " + AITile.LowerTile(7958, AITile.SLOPE_EW));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" LowerTile(): " + AITile.LowerTile(33924, AITile.SLOPE_ELEVATED));
print(" LowerTile(): " + AITile.LowerTile(33923, AITile.SLOPE_ELEVATED));
print(" RaiseTile(): " + AITile.RaiseTile(34193, AITile.SLOPE_ELEVATED));
print(" LowerTile(): " + AITile.LowerTile(34193, AITile.SLOPE_ELEVATED));
print(" LowerTile(): " + AITile.LowerTile(34192, AITile.SLOPE_NE));
print(" RaiseTile(): " + AITile.RaiseTile(34193, AITile.SLOPE_ELEVATED));
print(" LowerTile(): " + AITile.LowerTile(34192, AITile.SLOPE_NE));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" RaiseTile(): " + AITile.RaiseTile(5687, AITile.SLOPE_N));
print(" LowerTile(): " + AITile.LowerTile(5687, AITile.SLOPE_SE));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" RaiseTile(): " + AITile.RaiseTile(23596, AITile.SLOPE_NE));
print(" LowerTile(): " + AITile.LowerTile(23596, AITile.SLOPE_NE));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" RaiseTile(): " + AITile.RaiseTile(28536, AITile.SLOPE_E));
print(" RaiseTile(): " + AITile.RaiseTile(28536, AITile.SLOPE_E));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" LevelTiles(): " + AITile.LevelTiles(28536, 29053));
print(" LevelTiles(): " + AITile.LevelTiles(28536, 29053));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" LevelTiles(): " + AITile.LevelTiles(22348, 24405));
print(" LevelTiles(): " + AITile.LevelTiles(27717, 29772));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" LowerTile(): " + AITile.LowerTile(61534, AITile.SLOPE_W));
print(" RaiseTile(): " + AITile.RaiseTile(61534, AITile.SLOPE_NE));
print(" RaiseTile(): " + AITile.RaiseTile(61534, AITile.SLOPE_N));
print(" LowerTile(): " + AITile.LowerTile(61534, AITile.SLOPE_W));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" RaiseTile(): " + AITile.RaiseTile(61534, AITile.SLOPE_N));
print(" LowerTile(): " + AITile.LowerTile(61533, AITile.SLOPE_E));
print(" LowerTile(): " + AITile.LowerTile(61534, AITile.SLOPE_E));
print(" GetCosts(): " + accounting.GetCosts());
accounting.ResetCosts();
print(" RaiseTile(): " + AITile.RaiseTile(4033, AITile.SLOPE_S));
print(" LowerTile(): " + AITile.LowerTile(4033, AITile.SLOPE_S));
print(" LowerTile(): " + AITile.LowerTile(4033, AITile.SLOPE_E));
print(" RaiseTile(): " + AITile.RaiseTile(4033, AITile.SLOPE_E));
print(" RaiseTile(): " + AITile.RaiseTile(4033, AITile.SLOPE_NWS));
print(" GetCosts(): " + accounting.GetCosts());
}
function Regression::Start()
{
this.TestInit();
@@ -2398,6 +2482,7 @@ function Regression::Start()
this.Math();
this.PriorityQueue();
this.Terraforming();
/* Check Valuate() is actually limited, MUST BE THE LAST TEST. */
print("--Valuate() with excessive CPU usage--")
@@ -2411,4 +2496,3 @@ function Regression::Start()
}
list.Valuate(Infinite);
}
+76 -14
View File
@@ -1643,7 +1643,6 @@ ERROR: IsEnd() is invalid as Begin() is never called
GetAirportHeight(9): -1
GetAirportCoverageRadius(9): -1
GetAirportNumHelipads(9): -1
GetBankBalance(): 1999999790
GetPrice(): 5400
BuildAirport(): true
IsHangarTile(): false
@@ -1653,11 +1652,11 @@ ERROR: IsEnd() is invalid as Begin() is never called
IsHangarTile(): true
IsAirportTile(): true
GetAirportType(): 0
GetBankBalance(): 1999989890
GetCosts(): 9900
RemoveAirport(): true
IsHangarTile(): false
IsAirportTile(): false
GetBankBalance(): 1999989626
GetCosts(): 264
BuildAirport(): true
--Bridge--
@@ -8413,7 +8412,6 @@ ERROR: IsEnd() is invalid as Begin() is never called
IsBuoyTile(): false
IsLockTile(): false
IsCanalTile(): false
GetBankBalance(): 1999979304
BuildWaterDepot(): true
BuildDock(): true
BuildBuoy(): true
@@ -8426,7 +8424,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
IsBuoyTile(): true
IsLockTile(): true
IsCanalTile(): true
GetBankBalance(): 1999964680
GetCosts(): 14624
--AIWaypointList(BUOY)--
Count(): 1
@@ -8445,7 +8443,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
IsBuoyTile(): false
IsLockTile(): false
IsCanalTile(): false
GetBankBalance(): 1999959285
GetCosts(): 5395
BuildWaterDepot(): true
BuildDock(): true
BuildBuoy(): true
@@ -8556,6 +8554,9 @@ ERROR: IsEnd() is invalid as Begin() is never called
Depot
IsRailTile(): false
BuildRailDepot(): false
RemoveRailDepot(): false
BuildRailDepot(): true
RemoveRailDepot(): true
BuildRailDepot(): false
BuildRailDepot(): true
BuildRailDepot(): true
@@ -10585,10 +10586,13 @@ ERROR: IsEnd() is invalid as Begin() is never called
GetWagonAge(): 0
GetWagonEngineType(): 65535
GetWagonAge(): -1
GetVehicleType(): 3
GetLength(): -1
--Refit--
GetBuildWithRefitCapacity(): -1
GetBuildWithRefitCapacity(): 0
GetBuildWithRefitCapacity(): 160
GetBuildWithRefitCapacity(): -1
BuildVehicleWithRefit(): 20
GetCapacity(): 160
GetCapacity(): 0
@@ -10628,11 +10632,11 @@ ERROR: IsEnd() is invalid as Begin() is never called
14 => 1
12 => 1
Age ListDump:
14 => 1
13 => 1
12 => 1
17 => 0
16 => 0
14 => 0
13 => 0
12 => 0
MaxAge ListDump:
16 => 10980
14 => 10980
@@ -10641,10 +10645,10 @@ ERROR: IsEnd() is invalid as Begin() is never called
12 => 5490
AgeLeft ListDump:
16 => 10980
14 => 10980
14 => 10979
17 => 7320
13 => 5490
12 => 5490
13 => 5489
12 => 5489
CurrentSpeed ListDump:
12 => 27
17 => 0
@@ -10662,7 +10666,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
16 => 0
14 => 0
13 => 0
12 => 0
12 => -1
ProfitLastYear ListDump:
17 => 0
16 => 0
@@ -10702,6 +10706,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
--Order--
GetOrderCount(): 0
GetOrderCount(): -1
GetOrderDestination(): -1
AreOrderFlagsValid(): true
AreOrderFlagsValid(): false
@@ -10872,6 +10877,63 @@ ERROR: IsEnd() is invalid as Begin() is never called
Clear(): (null : 0x00000000)
IsEmpty(): true
Count(): 0
--Terraforming--
DemolishTile(): true
DemolishTile(): true
GetCosts(): 120
LowerTile(): false
RaiseTile(): true
GetCosts(): 60561
LowerTile(): true
GetCosts(): 561
LowerTile(): true
RaiseTile(): true
GetCosts(): 30958
RaiseTile(): false
LowerTile(): false
LowerTile(): true
RaiseTile(): true
LowerTile(): true
GetCosts(): 3078
LowerTile(): false
LowerTile(): true
RaiseTile(): false
LowerTile(): true
LowerTile(): false
RaiseTile(): true
LowerTile(): true
GetCosts(): 5701
RaiseTile(): true
LowerTile(): true
GetCosts(): 16055
RaiseTile(): false
LowerTile(): true
GetCosts(): 2076
RaiseTile(): true
RaiseTile(): true
GetCosts(): 10222
LevelTiles(): true
LevelTiles(): false
GetCosts(): 9778
LevelTiles(): true
LevelTiles(): true
GetCosts(): 288629
LowerTile(): false
RaiseTile(): true
RaiseTile(): false
LowerTile(): true
GetCosts(): 6099
RaiseTile(): true
LowerTile(): true
LowerTile(): false
GetCosts(): 1317
RaiseTile(): false
LowerTile(): true
LowerTile(): false
RaiseTile(): false
RaiseTile(): true
GetCosts(): 38996
--Valuate() with excessive CPU usage--
constructor failed with: excessive CPU usage in list filter function
Your script made an error: excessive CPU usage in valuator function
@@ -10880,7 +10942,7 @@ CALLSTACK WITH LOCALS
*FUNCTION [Valuate()] Valuate line [5]
[args] ARRAY
[this] INSTANCE
*FUNCTION [Start()] regression/main.nut line [2412]
*FUNCTION [Start()] regression/main.nut line [2497]
[Infinite] CLOSURE
[list] INSTANCE
[this] INSTANCE
+10
View File
@@ -50,6 +50,11 @@ add_files(
CONDITION OpusFile_FOUND
)
add_files(
soundresampler_soxr.cpp
CONDITION Soxr_FOUND
)
add_files(
aircraft.h
aircraft_cmd.cpp
@@ -139,6 +144,7 @@ add_files(
date_gui.h
debug.cpp
debug.h
debug_type.h
dedicated.cpp
depot.cpp
depot_base.h
@@ -336,6 +342,7 @@ add_files(
newgrf_town.h
newgrf_townname.cpp
newgrf_townname.h
newgrf_type.h
news_cmd.h
news_func.h
news_gui.cpp
@@ -399,6 +406,8 @@ add_files(
roadveh_cmd.h
roadveh_gui.cpp
safeguards.h
screensaver.cpp
screensaver.h
screenshot_bmp.cpp
screenshot_gui.cpp
screenshot_gui.h
@@ -450,6 +459,7 @@ add_files(
soundloader_type.h
soundloader_raw.cpp
soundloader_wav.cpp
soundresampler_type.h
source_type.h
sprite.cpp
sprite.h
+1 -1
View File
@@ -10,7 +10,7 @@
#ifndef AI_HPP
#define AI_HPP
#include "../script/api/script_event_types.hpp"
#include "../script/api/script_event.hpp"
#include "ai_scanner.hpp"
/**
+15 -5
View File
@@ -69,6 +69,16 @@
return;
}
/**
* Get the \c PerformanceElement for the AI of the given company.
* @param company The company to get the PerformanceElement for.
* @return The \c PerformanceElement.
*/
static constexpr PerformanceElement GetAIPerformanceElement(CompanyID company)
{
return static_cast<PerformanceElement>(PerformanceElement::AI0 + company);
}
/* static */ void AI::GameLoop()
{
/* If we are in networking, only servers run this function, and that only if it is allowed */
@@ -81,7 +91,7 @@
for (const Company *c : Company::Iterate()) {
if (c->is_ai) {
PerformanceMeasurer framerate((PerformanceElement)(PFE_AI0 + c->index));
PerformanceMeasurer framerate(GetAIPerformanceElement(c->index));
AutoRestoreBackup cur_company(_current_company, c->index);
c->ai_instance->GameLoop();
/* Occasionally collect garbage; every 255 ticks do one company.
@@ -90,7 +100,7 @@
c->ai_instance->CollectGarbage();
}
} else {
PerformanceMeasurer::SetInactive((PerformanceElement)(PFE_AI0 + c->index));
PerformanceMeasurer::SetInactive(GetAIPerformanceElement(c->index));
}
}
}
@@ -103,7 +113,7 @@
/* static */ void AI::Stop(CompanyID company)
{
if (_networking && !_network_server) return;
PerformanceMeasurer::SetInactive((PerformanceElement)(PFE_AI0 + company));
PerformanceMeasurer::SetInactive(GetAIPerformanceElement(company));
AutoRestoreBackup cur_company(_current_company, company);
Company *c = Company::Get(company);
@@ -189,14 +199,14 @@
for (CompanyID c = CompanyID::Begin(); c < MAX_COMPANIES; ++c) {
if (_settings_game.script_config.ai[c] != nullptr && _settings_game.script_config.ai[c]->HasScript()) {
if (!_settings_game.script_config.ai[c]->ResetInfo(true)) {
Debug(script, 0, "After a reload, the AI by the name '{}' was no longer found, and removed from the list.", _settings_game.script_config.ai[c]->GetName());
Debug(Facility::Script, Severity::Critical, "After a reload, the AI by the name '{}' was no longer found, and removed from the list.", _settings_game.script_config.ai[c]->GetName());
_settings_game.script_config.ai[c]->Change(std::nullopt);
}
}
if (_settings_newgame.script_config.ai[c] != nullptr && _settings_newgame.script_config.ai[c]->HasScript()) {
if (!_settings_newgame.script_config.ai[c]->ResetInfo(false)) {
Debug(script, 0, "After a reload, the AI by the name '{}' was no longer found, and removed from the list.", _settings_newgame.script_config.ai[c]->GetName());
Debug(Facility::Script, Severity::Critical, "After a reload, the AI by the name '{}' was no longer found, and removed from the list.", _settings_newgame.script_config.ai[c]->GetName());
_settings_newgame.script_config.ai[c]->Change(std::nullopt);
}
}
+7 -5
View File
@@ -22,6 +22,8 @@
#include "ai_info.hpp"
#include "../script/script_gui.h"
#include "../widgets/ai_widget.h"
#include "table/strings.h"
#include "../safeguards.h"
@@ -70,11 +72,11 @@ static constexpr std::initializer_list<NWidgetPart> _nested_ai_config_widgets =
NWidget(NWID_VERTICAL, NWidContainerFlag::EqualSize),
NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_OPEN_URL), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_CONTENT_OPEN_URL, STR_CONTENT_OPEN_URL_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_TEXTFILE + TFT_README), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_TEXTFILE + TextfileType::Readme), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
EndContainer(),
NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_TEXTFILE + TFT_CHANGELOG), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_TEXTFILE + TFT_LICENSE), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_TEXTFILE + TextfileType::Changelog), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, Colours::Yellow, WID_AIC_TEXTFILE + TextfileType::License), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
EndContainer(),
EndContainer(),
EndContainer(),
@@ -215,7 +217,7 @@ struct AIConfigWindow : public Window {
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
if (widget >= WID_AIC_TEXTFILE && widget < WID_AIC_TEXTFILE + TFT_CONTENT_END) {
if (widget >= WID_AIC_TEXTFILE && widget < WID_AIC_TEXTFILE + TextfileType::ContentEnd) {
if (this->selected_slot == CompanyID::Invalid() || AIConfig::GetConfig(this->selected_slot) == nullptr) return;
ShowScriptTextfileWindow(this, static_cast<TextfileType>(widget - WID_AIC_TEXTFILE), this->selected_slot);
@@ -326,7 +328,7 @@ struct AIConfigWindow : public Window {
this->SetWidgetDisabledState(WID_AIC_MOVE_DOWN, !IsEditable(this->selected_slot) || !IsEditable(static_cast<CompanyID>(this->selected_slot + 1)));
this->SetWidgetDisabledState(WID_AIC_OPEN_URL, this->selected_slot == CompanyID::Invalid() || config->GetInfo() == nullptr || config->GetInfo()->GetURL().empty());
for (TextfileType tft : EnumRange(TFT_CONTENT_BEGIN, TFT_CONTENT_END)) {
for (TextfileType tft : EnumRange(TextfileType::ContentBegin, TextfileType::ContentEnd)) {
this->SetWidgetDisabledState(WID_AIC_TEXTFILE + tft, this->selected_slot == CompanyID::Invalid() || !config->GetTextfile(tft, this->selected_slot).has_value());
}
}
+2 -2
View File
@@ -54,7 +54,7 @@ void AIScannerInfo::RegisterAPI(class Squirrel &engine)
AIInfo *AIScannerInfo::SelectRandomAI() const
{
if (_game_mode == GameMode::Menu) {
Debug(script, 0, "The intro game should not use AI, loading 'dummy' AI.");
Debug(Facility::Script, Severity::Critical, "The intro game should not use AI, loading 'dummy' AI.");
return this->info_dummy.get();
}
@@ -63,7 +63,7 @@ AIInfo *AIScannerInfo::SelectRandomAI() const
uint num_random_ais = std::ranges::distance(random_ais);
if (num_random_ais == 0) {
Debug(script, 0, "No suitable AI found, loading 'dummy' AI.");
Debug(Facility::Script, Severity::Critical, "No suitable AI found, loading 'dummy' AI.");
return this->info_dummy.get();
}
+16 -12
View File
@@ -37,6 +37,9 @@
#include "framerate_type.h"
#include "aircraft_cmd.h"
#include "vehicle_cmd.h"
#include "script/api/script_event_types.hpp"
#include "widgets/vehicle_widget.h"
#include "table/strings.h"
@@ -152,8 +155,8 @@ static StationID FindNearestHangar(const Aircraft *v)
/* Check if our last and next destinations can be reached from the depot airport. */
if (max_range != 0) {
uint last_dist = (last_dest != nullptr && last_dest->airport.tile != INVALID_TILE) ? DistanceSquare(st->airport.tile, last_dest->airport.tile) : 0;
uint next_dist = (next_dest != nullptr && next_dest->airport.tile != INVALID_TILE) ? DistanceSquare(st->airport.tile, next_dest->airport.tile) : 0;
uint last_dist = (last_dest != nullptr && !last_dest->airport.IsEmpty()) ? DistanceSquare(st->airport.tile, last_dest->airport.tile) : 0;
uint next_dist = (next_dest != nullptr && !next_dest->airport.IsEmpty()) ? DistanceSquare(st->airport.tile, next_dest->airport.tile) : 0;
if (last_dist > max_range || next_dist > max_range) continue;
}
@@ -832,7 +835,7 @@ static uint8_t AircraftGetEntryPoint(const Aircraft *v, const AirportFTAClass *a
const Station *st = Station::GetIfValid(v->targetairport);
if (st != nullptr) {
/* Make sure we don't go to INVALID_TILE if the airport has been removed. */
tile = (st->airport.tile != INVALID_TILE) ? st->airport.tile : st->xy;
tile = !st->airport.IsEmpty() ? st->airport.tile : st->xy;
}
int delta_x = v->x_pos - TileX(tile) * TILE_SIZE;
@@ -869,7 +872,7 @@ static bool AircraftController(Aircraft *v)
Direction rotation = Direction::N;
uint size_x = 1, size_y = 1;
if (st != nullptr) {
if (st->airport.tile != INVALID_TILE) {
if (!st->airport.IsEmpty()) {
tile = st->airport.tile;
rotation = st->airport.rotation;
size_x = st->airport.w;
@@ -882,7 +885,7 @@ static bool AircraftController(Aircraft *v)
const AirportFTAClass *afc = tile == INVALID_TILE ? GetAirport(AT_DUMMY) : st->airport.GetFTA();
/* prevent going to INVALID_TILE if airport is deleted. */
if (st == nullptr || st->airport.tile == INVALID_TILE) {
if (st == nullptr || st->airport.IsEmpty()) {
/* Jump into our "holding pattern" state machine if possible */
if (v->pos >= afc->nofelements) {
v->pos = v->previous_pos = AircraftGetEntryPoint(v, afc, Direction::N);
@@ -1141,7 +1144,7 @@ static bool AircraftController(Aircraft *v)
continue;
}
if (st->airport.tile == INVALID_TILE) {
if (st->airport.IsEmpty()) {
/* Airport has been removed, abort the landing procedure */
v->state = FLYING;
UpdateAircraftCache(v);
@@ -1325,6 +1328,7 @@ void Aircraft::MarkDirty()
if (this->subtype == AIR_HELICOPTER) {
GetRotorImage(this, EngineImageType::OnMap, &this->Next()->Next()->sprite_cache.sprite_seq);
}
UpdateAircraftCache(this);
}
@@ -1819,7 +1823,7 @@ static bool AirportMove(Aircraft *v, const AirportFTAClass *apc)
{
/* error handling */
if (v->pos >= apc->nofelements) {
Debug(misc, 0, "[Ap] position {} is not valid for current airport. Max position is {}", v->pos, apc->nofelements - 1);
Debug(Facility::Misc, Severity::Critical, "[Ap] position {} is not valid for current airport. Max position is {}", v->pos, apc->nofelements - 1);
assert(v->pos < apc->nofelements);
}
@@ -1858,7 +1862,7 @@ static bool AirportMove(Aircraft *v, const AirportFTAClass *apc)
current = current->next.get();
} while (current != nullptr);
Debug(misc, 0, "[Ap] cannot move further on Airport! (pos {} state {}) for vehicle {}", v->pos, v->state, v->index);
Debug(Facility::Misc, Severity::Critical, "[Ap] cannot move further on Airport! (pos {} state {}) for vehicle {}", v->pos, v->state, v->index);
NOT_REACHED();
}
@@ -2126,7 +2130,7 @@ static bool AircraftEventHandler(Aircraft *v, int loop)
Station *cur_st = Station::GetIfValid(v->targetairport);
Station *next_st = v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_DEPOT) ? Station::GetIfValid(v->current_order.GetDestination().ToStationID()) : nullptr;
if (cur_st != nullptr && cur_st->airport.tile != INVALID_TILE && next_st != nullptr && next_st->airport.tile != INVALID_TILE) {
if (cur_st != nullptr && !cur_st->airport.IsEmpty() && next_st != nullptr && !next_st->airport.IsEmpty()) {
uint dist = DistanceSquare(cur_st->airport.tile, next_st->airport.tile);
AircraftHandleDestTooFar(v, dist > v->acache.cached_max_range_sqr);
}
@@ -2141,7 +2145,7 @@ bool Aircraft::Tick()
{
if (!this->IsNormalAircraft()) return true;
PerformanceAccumulator framerate(PFE_GL_AIRCRAFT);
PerformanceAccumulator framerate(PerformanceElement::GameLoopAircraft);
this->tick_counter++;
@@ -2173,7 +2177,7 @@ Station *GetTargetAirportIfValid(const Aircraft *v)
Station *st = Station::GetIfValid(v->targetairport);
if (st == nullptr) return nullptr;
return st->airport.tile == INVALID_TILE ? nullptr : st;
return st->airport.IsEmpty() ? nullptr : st;
}
/**
@@ -2184,7 +2188,7 @@ void UpdateAirplanesOnNewStation(const Station *st)
{
/* only 1 station is updated per function call, so it is enough to get entry_point once */
const AirportFTAClass *ap = st->airport.GetFTA();
Direction rotation = st->airport.tile == INVALID_TILE ? Direction::N : st->airport.rotation;
Direction rotation = st->airport.IsEmpty() ? Direction::N : st->airport.rotation;
for (Aircraft *v : Aircraft::Iterate()) {
if (!v->IsNormalAircraft() || v->targetairport != st->index) continue;
+1 -1
View File
@@ -74,7 +74,7 @@ void AddAnimatedTile(TileIndex tile, bool mark_dirty)
*/
void AnimateAnimatedTiles()
{
PerformanceAccumulator landscape_framerate(PFE_GL_LANDSCAPE);
PerformanceAccumulator landscape_framerate(PerformanceElement::GameLoopLandscape);
for (auto it = std::begin(_animated_tiles); it != std::end(_animated_tiles); /* nothing */) {
TileIndex &tile = *it;
+1
View File
@@ -357,6 +357,7 @@ void AddArticulatedParts(Vehicle *first)
t->subtype = 0;
t->track = front->track;
t->railtypes = front->railtypes;
t->flags.Set(VehicleRailFlag::AllowedOnNormalRail, _settings_game.vehicle.disable_elrails && RailVehInfo(front->engine_type)->intended_railtypes.Test(RAILTYPE_ELECTRIC));
t->spritenum = e_artic->VehInfo<RailVehicleInfo>().image_index;
if (e_artic->CanCarryCargo()) {
+9 -8
View File
@@ -28,6 +28,7 @@
#include "order_cmd.h"
#include "train_cmd.h"
#include "vehicle_cmd.h"
#include "script/api/script_event_types.hpp"
#include "table/strings.h"
@@ -357,7 +358,7 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic
/* Build the new vehicle */
VehicleID new_veh_id;
std::tie(cost, new_veh_id, std::ignore, std::ignore, std::ignore) = Command<Commands::BuildVehicle>::Do({DoCommandFlag::Execute, DoCommandFlag::AutoReplace}, old_veh->tile, e, true, INVALID_CARGO, INVALID_CLIENT_ID);
std::tie(cost, new_veh_id, std::ignore, std::ignore, std::ignore) = Command<Commands::BuildVehicle>::Do({DoCommandFlag::Execute, DoCommandFlag::AutoReplace}, old_veh->tile, e, true, INVALID_CARGO, ClientID::Invalid);
if (cost.Failed()) return cost;
Vehicle *new_veh = Vehicle::Get(new_veh_id);
@@ -489,11 +490,11 @@ static CommandCost ReplaceFreeUnit(Vehicle **single_unit, DoCommandFlags flags,
}
/* Sell the old vehicle */
cost.AddCost(Command<Commands::SellVehicle>::Do(flags, old_v->index, false, false, INVALID_CLIENT_ID));
cost.AddCost(Command<Commands::SellVehicle>::Do(flags, old_v->index, false, false, ClientID::Invalid));
/* If we are not in DoCommandFlag::Execute undo everything */
if (!flags.Test(DoCommandFlag::Execute)) {
Command<Commands::SellVehicle>::Do(DoCommandFlag::Execute, new_v->index, false, false, INVALID_CLIENT_ID);
Command<Commands::SellVehicle>::Do(DoCommandFlag::Execute, new_v->index, false, false, ClientID::Invalid);
}
}
@@ -633,7 +634,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlags flags, bool wago
assert(RailVehInfo(wagon->engine_type)->railveh_type == RailVehicleType::Wagon);
/* Sell wagon */
[[maybe_unused]] CommandCost ret = Command<Commands::SellVehicle>::Do(DoCommandFlag::Execute, wagon->index, false, false, INVALID_CLIENT_ID);
[[maybe_unused]] CommandCost ret = Command<Commands::SellVehicle>::Do(DoCommandFlag::Execute, wagon->index, false, false, ClientID::Invalid);
assert(ret.Succeeded());
it->new_veh = nullptr;
@@ -665,7 +666,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlags flags, bool wago
/* Sell the vehicle.
* Note: This might temporarily construct new trains, so use DoCommandFlag::AutoReplace to prevent
* it from failing due to engine limits. */
cost.AddCost(Command<Commands::SellVehicle>::Do(DoCommandFlags{flags}.Set(DoCommandFlag::AutoReplace), w->index, false, false, INVALID_CLIENT_ID));
cost.AddCost(Command<Commands::SellVehicle>::Do(DoCommandFlags{flags}.Set(DoCommandFlag::AutoReplace), w->index, false, false, ClientID::Invalid));
if (flags.Test(DoCommandFlag::Execute)) {
it->old_veh = nullptr;
if (it == std::begin(replacements)) old_head = nullptr;
@@ -696,7 +697,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlags flags, bool wago
if (!flags.Test(DoCommandFlag::Execute)) {
for (auto it = std::rbegin(replacements); it != std::rend(replacements); ++it) {
if (it->new_veh != nullptr) {
Command<Commands::SellVehicle>::Do(DoCommandFlag::Execute, it->new_veh->index, false, false, INVALID_CLIENT_ID);
Command<Commands::SellVehicle>::Do(DoCommandFlag::Execute, it->new_veh->index, false, false, ClientID::Invalid);
it->new_veh = nullptr;
}
}
@@ -723,12 +724,12 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlags flags, bool wago
}
/* Sell the old vehicle */
cost.AddCost(Command<Commands::SellVehicle>::Do(flags, old_head->index, false, false, INVALID_CLIENT_ID));
cost.AddCost(Command<Commands::SellVehicle>::Do(flags, old_head->index, false, false, ClientID::Invalid));
}
/* If we are not in DoCommandFlag::Execute undo everything */
if (!flags.Test(DoCommandFlag::Execute)) {
Command<Commands::SellVehicle>::Do(DoCommandFlag::Execute, new_head->index, false, false, INVALID_CLIENT_ID);
Command<Commands::SellVehicle>::Do(DoCommandFlag::Execute, new_head->index, false, false, ClientID::Invalid);
}
}
}
+1 -1
View File
@@ -450,7 +450,7 @@ public:
str = GetString(STR_REPLACE_NOT_REPLACING_VEHICLE_SELECTED);
}
DrawString(r.Shrink(WidgetDimensions::scaled.frametext, WidgetDimensions::scaled.framerect), std::move(str), TextColour::Black, SA_HOR_CENTER);
DrawString(r.Shrink(WidgetDimensions::scaled.frametext, WidgetDimensions::scaled.framerect), std::move(str), TextColour::Black, AlignmentH::Centre);
break;
}
+2 -1
View File
@@ -10,6 +10,7 @@
#ifndef BASE_MEDIA_BASE_H
#define BASE_MEDIA_BASE_H
#include "debug_type.h"
#include "fileio_func.h"
#include "textfile_type.h"
#include "textfile_gui.h"
@@ -93,7 +94,7 @@ struct BaseSet {
return BaseSet<T>::NUM_FILES - this->valid_files;
}
void LogError(std::string_view full_filename, std::string_view detail, int level = 0) const;
void LogError(std::string_view full_filename, std::string_view detail, Severity severity = {}) const;
const IniItem *GetMandatoryItem(std::string_view full_filename, const IniGroup &group, std::string_view name) const;
bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename = true);
+33 -19
View File
@@ -21,13 +21,13 @@ extern void CheckExternalFiles();
* Log error from reading basesets.
* @param full_filename the full filename of the loaded file
* @param detail detail log message
* @param level debug level
* @param severity debug severity
*/
template <class T>
void BaseSet<T>::LogError(std::string_view full_filename, std::string_view detail, int level) const
void BaseSet<T>::LogError(std::string_view full_filename, std::string_view detail, Severity severity) const
{
Debug(misc, level, "Loading base {}set details failed: {}", BaseSet<T>::SET_TYPE, full_filename);
Debug(misc, level, " {}", detail);
Debug(Facility::Misc, severity, "Loading base {}set details failed: {}", BaseSet<T>::SET_TYPE, full_filename);
Debug(Facility::Misc, severity, " {}", detail);
}
/**
@@ -47,6 +47,22 @@ const IniItem *BaseSet<T>::GetMandatoryItem(std::string_view full_filename, cons
return nullptr;
}
/**
* Helper to decode a 4 character short name into an uint32_t representation.
* @param shortname The short name.
* @return The uint32_t representation.
*/
constexpr uint32_t DecodeShortName(std::string_view shortname)
{
/* The short name is documented to be exactly 4 characters long, see docs/ob[gms]_format.txt. */
shortname = shortname.substr(0, 4);
uint32_t encoded = 0;
for (size_t i = 0; i < shortname.size(); i++) {
encoded |= static_cast<uint8_t>(shortname[i]) << (i * 8);
}
return encoded;
}
/**
* Read the set information from a loaded ini.
* @param ini the ini to read from
@@ -85,9 +101,7 @@ bool BaseSet<T>::FillSetDetails(const IniFile &ini, const std::string &path, con
item = this->GetMandatoryItem(full_filename, *metadata, "shortname");
if (item == nullptr) return false;
for (uint i = 0; (*item->value)[i] != '\0' && i < 4; i++) {
this->shortname |= ((uint8_t)(*item->value)[i]) << (i * 8);
}
this->shortname = DecodeShortName(*item->value);
item = this->GetMandatoryItem(full_filename, *metadata, "version");
if (item == nullptr) return false;
@@ -111,10 +125,10 @@ bool BaseSet<T>::FillSetDetails(const IniFile &ini, const std::string &path, con
const IniGroup *origin = ini.GetGroup("origin");
auto file_names = BaseSet<T>::GetFilenames();
bool original_set =
std::byteswap(this->shortname) == 'TTDD' || // TTD DOS graphics, TTD DOS music
std::byteswap(this->shortname) == 'TTDW' || // TTD WIN graphics, TTD WIN music
std::byteswap(this->shortname) == 'TTDO' || // TTD sound
std::byteswap(this->shortname) == 'TTOD'; // TTO music
this->shortname == DecodeShortName("TTDD") || // TTD DOS graphics, TTD DOS music
this->shortname == DecodeShortName("TTDW") || // TTD WIN graphics, TTD WIN music
this->shortname == DecodeShortName("TTDO") || // TTD sound
this->shortname == DecodeShortName("TTOD"); // TTO music
for (uint i = 0; i < BaseSet<T>::NUM_FILES; i++) {
MD5File *file = &this->files[i];
@@ -151,7 +165,7 @@ bool BaseSet<T>::FillSetDetails(const IniFile &ini, const std::string &path, con
item = origin != nullptr ? origin->GetItem(filename) : nullptr;
if (item == nullptr) item = origin != nullptr ? origin->GetItem("default") : nullptr;
if (item == nullptr || !item->value.has_value()) {
this->LogError(full_filename, fmt::format("origin.{} field missing", filename), 1);
this->LogError(full_filename, fmt::format("origin.{} field missing", filename), Severity::Error);
file->missing_warning.clear();
} else {
file->missing_warning = item->value.value();
@@ -169,13 +183,13 @@ bool BaseSet<T>::FillSetDetails(const IniFile &ini, const std::string &path, con
case MD5File::ChecksumResult::Mismatch:
/* This is normal for original sample.cat, which either matches with orig_dos or orig_win. */
this->LogError(full_filename, fmt::format("MD5 checksum mismatch for: {}", filename), original_set ? 1 : 0);
this->LogError(full_filename, fmt::format("MD5 checksum mismatch for: {}", filename), original_set ? Severity::Error : Severity::Critical);
this->found_files++;
break;
case MD5File::ChecksumResult::NoFile:
/* Missing files is normal for the original basesets. Use lower debug level */
this->LogError(full_filename, fmt::format("File is missing: {}", filename), original_set ? 1 : 0);
this->LogError(full_filename, fmt::format("File is missing: {}", filename), original_set ? Severity::Error : Severity::Critical);
break;
}
}
@@ -186,7 +200,7 @@ bool BaseSet<T>::FillSetDetails(const IniFile &ini, const std::string &path, con
template <class Tbase_set>
bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_length, const std::string &)
{
Debug(misc, 1, "Checking {} for base {} set", filename, BaseSet<Tbase_set>::SET_TYPE);
Debug(Facility::Misc, Severity::Error, "Checking {} for base {} set", filename, BaseSet<Tbase_set>::SET_TYPE);
auto set = std::make_unique<Tbase_set>();
IniFile ini{};
@@ -208,7 +222,7 @@ bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_
if (((*existing)->valid_files == set->valid_files && (*existing)->version >= set->version) ||
(*existing)->valid_files > set->valid_files) {
Debug(misc, 1, "Not adding {} ({}) as base {} set (duplicate, {})", set->name, fmt::join(set->version, "."),
Debug(Facility::Misc, Severity::Error, "Not adding {} ({}) as base {} set (duplicate, {})", set->name, fmt::join(set->version, "."),
BaseSet<Tbase_set>::SET_TYPE,
(*existing)->valid_files > set->valid_files ? "fewer valid files" : "lower version");
@@ -224,16 +238,16 @@ bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_
/* Keep baseset configuration, if compatible */
set->CopyCompatibleConfig(**existing);
Debug(misc, 1, "Removing {} ({}) as base {} set (duplicate, {})", (*existing)->name, fmt::join((*existing)->version, "."), BaseSet<Tbase_set>::SET_TYPE,
Debug(Facility::Misc, Severity::Error, "Removing {} ({}) as base {} set (duplicate, {})", (*existing)->name, fmt::join((*existing)->version, "."), BaseSet<Tbase_set>::SET_TYPE,
(*existing)->valid_files < set->valid_files ? "fewer valid files" : "lower version");
/* Existing set is worse, move it to duplicates and replace with the current set. */
duplicate_sets.push_back(std::move(*existing));
Debug(misc, 1, "Adding {} ({}) as base {} set", set->name, fmt::join(set->version, "."), BaseSet<Tbase_set>::SET_TYPE);
Debug(Facility::Misc, Severity::Error, "Adding {} ({}) as base {} set", set->name, fmt::join(set->version, "."), BaseSet<Tbase_set>::SET_TYPE);
*existing = std::move(set);
} else {
Debug(grf, 1, "Adding {} ({}) as base {} set", set->name, set->version, BaseSet<Tbase_set>::SET_TYPE);
Debug(Facility::Misc, Severity::Error, "Adding {} ({}) as base {} set", set->name, set->version, BaseSet<Tbase_set>::SET_TYPE);
available_sets.push_back(std::move(set));
}
+2 -24
View File
@@ -22,7 +22,7 @@ extern StationPool _station_pool;
template <typename T>
struct SpecMapping {
const T *spec = nullptr; ///< Custom spec.
uint32_t grfid = 0; ///< GRF ID of this custom spec.
GrfID grfid{}; ///< GRF ID of this custom spec.
uint16_t localidx = 0; ///< Local ID within GRF of this custom spec.
};
@@ -32,28 +32,6 @@ struct RoadStopTileData {
uint8_t animation_frame = 0;
};
/** StationRect - used to track station spread out rectangle - cheaper than scanning whole map */
struct StationRect : public Rect {
enum StationRectMode : uint8_t {
ADD_TEST = 0,
ADD_TRY,
ADD_FORCE
};
StationRect();
void MakeEmpty();
bool PtInExtendedRect(int x, int y, int distance = 0) const;
bool IsEmpty() const;
CommandCost BeforeAddTile(TileIndex tile, StationRectMode mode);
CommandCost BeforeAddRect(TileIndex tile, int w, int h, StationRectMode mode);
bool AfterRemoveTile(BaseStation *st, TileIndex tile);
bool AfterRemoveRect(BaseStation *st, TileArea ta);
static bool ScanForStationTiles(StationID st_id, int left_a, int top_a, int right_a, int bottom_a);
StationRect& operator = (const Rect &src);
};
/** Base class for all station-ish types */
struct BaseStation : StationPool::PoolItem<&_station_pool> {
TileIndex xy = INVALID_TILE; ///< Base tile of the station
@@ -82,7 +60,7 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
CargoTypes cached_roadstop_cargo_triggers{}; ///< NOSAVE: Combined cargo trigger bitmask for road stops
TileArea train_station{INVALID_TILE, 0, 0}; ///< Tile area the train 'station' part covers
StationRect rect{}; ///< NOSAVE: Station spread out rectangle maintained by StationRect::xxx() functions
TileArea spread{}; ///< NOSAVE: Station spread tile area.
std::vector<RoadStopTileData> custom_roadstop_tile_data{}; ///< List of custom road stop tile data
-18
View File
@@ -50,19 +50,6 @@ public:
this->data.clear();
}
/**
* Initialize the BitmapTileArea with the specified Rect.
* @param r Rect to use.
*/
void Initialize(const Rect &r)
{
this->tile = TileXY(r.left, r.top);
this->w = r.Width();
this->h = r.Height();
this->data.clear();
this->data.resize(Index(w, h));
}
void Initialize(const TileArea &ta)
{
this->tile = ta.tile;
@@ -125,11 +112,6 @@ public:
}
return *this;
}
std::unique_ptr<TileIterator> Clone() const override
{
return std::make_unique<BitmapTileIterator>(*this);
}
};
#endif /* BITMAP_TYPE_HPP */
+1 -1
View File
@@ -318,7 +318,7 @@ void Blitter_32bppAnim::DrawColourMappingRect(void *dst, int width, int height,
return;
}
Debug(misc, 0, "32bpp blitter doesn't know how to draw this colour table ('{}')", pal);
Debug(Facility::Misc, Severity::Critical, "32bpp blitter doesn't know how to draw this colour table ('{}')", pal);
}
void Blitter_32bppAnim::SetPixel(void *video, int x, int y, PixelColour colour)
+37 -25
View File
@@ -43,7 +43,7 @@ inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom
const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width;
const Colour *src_rgba_line = (const Colour *) ((const uint8_t *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size);
if (read_mode != RM_WITH_MARGIN) {
if (read_mode != ReadMode::WithMargin) {
src_rgba_line += bp->skip_left;
src_mv_line += bp->skip_left;
}
@@ -61,8 +61,8 @@ inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom
if (mode != BlitterMode::Transparent) src_mv = src_mv_line;
uint16_t *anim = anim_line;
if (read_mode == RM_WITH_MARGIN) {
assert(bt_last == BT_NONE); // or you must ensure block type is preserved
if (read_mode == ReadMode::WithMargin) {
assert(bt_last == BlockType::None); // or you must ensure block type is preserved
anim += src_rgba_line[0].data;
src += src_rgba_line[0].data;
dst += src_rgba_line[0].data;
@@ -155,7 +155,7 @@ bmno_full_transparency:
dst += 2;
}
if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) {
if ((bt_last == BlockType::None && effective_width & 1) || bt_last == BlockType::Odd) {
if (src->a == 0) {
/* Complete transparency. */
} else if (src->a == 255) {
@@ -266,7 +266,7 @@ bmcr_full_transparency:
anim += 2;
}
if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) {
if ((bt_last == BlockType::None && effective_width & 1) || bt_last == BlockType::Odd) {
/* In case the m-channel is zero, do not remap this pixel in any way. */
__m128i srcABCD;
if (src->a == 0) break;
@@ -309,7 +309,7 @@ bmcr_alpha_blend_single:
if (src[-1].a) anim[-1] = 0;
}
if ((bt_last == BT_NONE && bp->width & 1) || bt_last == BT_ODD) {
if ((bt_last == BlockType::None && bp->width & 1) || bt_last == BlockType::Odd) {
__m128i srcABCD = _mm_cvtsi32_si128(src->data);
__m128i dstABCD = _mm_cvtsi32_si128(dst->data);
dst->data = _mm_cvtsi128_si32(DarkenTwoPixels(srcABCD, dstABCD, a_cm, tr_nom_base));
@@ -373,6 +373,25 @@ next_line:
}
}
/**
* Draws a sprite to a (screen) buffer. It is templated to allow faster operation.
*
* @tparam mode blitter mode
* @param bp further blitting parameters
* @param zoom zoom level at which we are drawing
* @param animated Whether the sprite is animated.
*/
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent>
inline void Blitter_32bppSSE4_Anim::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom, bool animated)
{
if (animated) {
this->Draw<mode, read_mode, bt_last, translucent, true>(bp, zoom);
} else {
this->Draw<mode, read_mode, bt_last, translucent, false>(bp, zoom);
}
}
/**
* Draws a sprite to a (screen) buffer. Calls adequate templated function.
*
@@ -394,25 +413,20 @@ void Blitter_32bppSSE4_Anim::Draw(Blitter::BlitterParams *bp, BlitterMode mode,
bm_normal:
if (bp->skip_left != 0 || bp->width <= MARGIN_NORMAL_THRESHOLD) {
const BlockType bt_last = (BlockType) (bp->width & 1);
if (bt_last == BT_EVEN) {
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true, false>(bp, zoom);
else Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true, true>(bp, zoom);
if (bt_last == BlockType::Even) {
Draw<BlitterMode::Normal, ReadMode::WithSkip, BlockType::Even, true>(bp, zoom, !sprite_flags.Test(SpriteFlag::NoAnim));
} else {
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true, false>(bp, zoom);
else Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true, true>(bp, zoom);
Draw<BlitterMode::Normal, ReadMode::WithSkip, BlockType::Odd, true>(bp, zoom, !sprite_flags.Test(SpriteFlag::NoAnim));
}
} else {
#ifdef POINTER_IS_64BIT
if (sprite_flags.Test(SpriteFlag::Translucent)) {
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
else Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
Draw<BlitterMode::Normal, ReadMode::WithMargin, BlockType::None, true>(bp, zoom, !sprite_flags.Test(SpriteFlag::NoAnim));
} else {
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, false, false>(bp, zoom);
else Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, false, true>(bp, zoom);
Draw<BlitterMode::Normal, ReadMode::WithMargin, BlockType::None, false>(bp, zoom, !sprite_flags.Test(SpriteFlag::NoAnim));
}
#else
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
else Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
Draw<BlitterMode::Normal, ReadMode::WithMargin, BlockType::None, true>(bp, zoom, !sprite_flags.Test(SpriteFlag::NoAnim));
#endif
}
break;
@@ -420,17 +434,15 @@ bm_normal:
case BlitterMode::ColourRemap:
if (sprite_flags.Test(SpriteFlag::NoRemap)) goto bm_normal;
if (bp->skip_left != 0 || bp->width <= MARGIN_REMAP_THRESHOLD) {
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true, false>(bp, zoom);
else Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true, true>(bp, zoom);
Draw<BlitterMode::ColourRemap, ReadMode::WithSkip, BlockType::None, true>(bp, zoom, !sprite_flags.Test(SpriteFlag::NoAnim));
} else {
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
else Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
Draw<BlitterMode::ColourRemap, ReadMode::WithMargin, BlockType::None, true>(bp, zoom, !sprite_flags.Test(SpriteFlag::NoAnim));
}
break;
case BlitterMode::Transparent: Draw<BlitterMode::Transparent, RM_NONE, BT_NONE, true, true>(bp, zoom); return;
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap, RM_NONE, BT_NONE, true, true>(bp, zoom); return;
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap, RM_NONE, BT_NONE, true, true>(bp, zoom); return;
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap, RM_NONE, BT_NONE, true, true>(bp, zoom); return;
case BlitterMode::Transparent: Draw<BlitterMode::Transparent, ReadMode::None, BlockType::None, true, true>(bp, zoom); return;
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap, ReadMode::None, BlockType::None, true, true>(bp, zoom); return;
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap, ReadMode::None, BlockType::None, true, true>(bp, zoom); return;
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap, ReadMode::None, BlockType::None, true, true>(bp, zoom); return;
}
}
+2
View File
@@ -38,6 +38,8 @@ private:
public:
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent, bool animated>
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent>
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom, bool animated);
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override
+1 -1
View File
@@ -112,7 +112,7 @@ void Blitter_32bppSimple::DrawColourMappingRect(void *dst, int width, int height
return;
}
Debug(misc, 0, "32bpp blitter doesn't know how to draw this colour table ('{}')", pal);
Debug(Facility::Misc, Severity::Critical, "32bpp blitter doesn't know how to draw this colour table ('{}')", pal);
}
Sprite *Blitter_32bppSimple::Encode(SpriteType, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
+8 -8
View File
@@ -39,17 +39,17 @@ public:
static_assert(sizeof(MapValue) == 2);
/** Helper for creating specialised functions for specific optimisations. */
enum ReadMode : uint8_t {
RM_WITH_SKIP, ///< Use normal code for skipping empty pixels.
RM_WITH_MARGIN, ///< Use cached number of empty pixels at begin and end of line to reduce work.
RM_NONE, ///< No specialisation.
enum class ReadMode : uint8_t {
WithSkip, ///< Use normal code for skipping empty pixels.
WithMargin, ///< Use cached number of empty pixels at begin and end of line to reduce work.
None, ///< No specialisation.
};
/** Helper for creating specialised functions for the case where the sprite width is odd or even. */
enum BlockType : uint8_t {
BT_EVEN, ///< An even number of pixels in the width; no need for a special case for the last pixel.
BT_ODD, ///< An odd number of pixels in the width; special case for the last pixel.
BT_NONE, ///< No specialisation for either case.
enum class BlockType : uint8_t {
Even, ///< An even number of pixels in the width; no need for a special case for the last pixel.
Odd, ///< An odd number of pixels in the width; special case for the last pixel.
None, ///< No specialisation for either case.
};
/** Helper for using specialised functions designed to prevent whenever it's possible things like:
+16 -16
View File
@@ -231,7 +231,7 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width;
const Colour *src_rgba_line = (const Colour *) ((const uint8_t *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size);
if (read_mode != RM_WITH_MARGIN) {
if (read_mode != ReadMode::WithMargin) {
src_rgba_line += bp->skip_left;
src_mv_line += bp->skip_left;
}
@@ -261,8 +261,8 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
const Colour *src = src_rgba_line + META_LENGTH;
if (mode == BlitterMode::ColourRemap || mode == BlitterMode::CrashRemap) src_mv = src_mv_line;
if (read_mode == RM_WITH_MARGIN) {
assert(bt_last == BT_NONE); // or you must ensure block type is preserved
if (read_mode == ReadMode::WithMargin) {
assert(bt_last == BlockType::None); // or you must ensure block type is preserved
src += src_rgba_line[0].data;
dst += src_rgba_line[0].data;
if (mode == BlitterMode::ColourRemap || mode == BlitterMode::CrashRemap) src_mv += src_rgba_line[0].data;
@@ -293,7 +293,7 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
dst += 2;
}
if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) {
if ((bt_last == BlockType::None && effective_width & 1) || bt_last == BlockType::Odd) {
__m128i srcABCD = _mm_cvtsi32_si128(src->data);
__m128i dstABCD = _mm_cvtsi32_si128(dst->data);
dst->data = _mm_cvtsi128_si32(AlphaBlendTwoPixels(srcABCD, dstABCD, ALPHA_BLEND_PARAM_1, ALPHA_BLEND_PARAM_2, ALPHA_BLEND_PARAM_3));
@@ -347,7 +347,7 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
src_mv += 2;
}
if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) {
if ((bt_last == BlockType::None && effective_width & 1) || bt_last == BlockType::Odd) {
#else
for (uint x = (uint) effective_width; x > 0; x--) {
#endif
@@ -392,7 +392,7 @@ bmcr_alpha_blend_single:
dst += 2;
}
if ((bt_last == BT_NONE && bp->width & 1) || bt_last == BT_ODD) {
if ((bt_last == BlockType::None && bp->width & 1) || bt_last == BlockType::Odd) {
__m128i srcABCD = _mm_cvtsi32_si128(src->data);
__m128i dstABCD = _mm_cvtsi32_si128(dst->data);
dst->data = _mm_cvtsi128_si32(DarkenTwoPixels(srcABCD, dstABCD, DARKEN_PARAM_1, DARKEN_PARAM_2));
@@ -468,14 +468,14 @@ void Blitter_32bppSSE4::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomL
bm_normal:
const BlockType bt_last = (BlockType) (bp->width & 1);
switch (bt_last) {
default: Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true>(bp, zoom); return;
case BT_ODD: Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true>(bp, zoom); return;
default: Draw<BlitterMode::Normal, ReadMode::WithSkip, BlockType::Even, true>(bp, zoom); return;
case BlockType::Odd: Draw<BlitterMode::Normal, ReadMode::WithSkip, BlockType::Odd, true>(bp, zoom); return;
}
} else {
if (((const Blitter_32bppSSE_Base::SpriteData *) bp->sprite)->flags.Test(SpriteFlag::Translucent)) {
Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true>(bp, zoom);
Draw<BlitterMode::Normal, ReadMode::WithMargin, BlockType::None, true>(bp, zoom);
} else {
Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, false>(bp, zoom);
Draw<BlitterMode::Normal, ReadMode::WithMargin, BlockType::None, false>(bp, zoom);
}
return;
}
@@ -484,14 +484,14 @@ bm_normal:
case BlitterMode::ColourRemap:
if (((const Blitter_32bppSSE_Base::SpriteData *) bp->sprite)->flags.Test(SpriteFlag::NoRemap)) goto bm_normal;
if (bp->skip_left != 0 || bp->width <= MARGIN_REMAP_THRESHOLD) {
Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true>(bp, zoom); return;
Draw<BlitterMode::ColourRemap, ReadMode::WithSkip, BlockType::None, true>(bp, zoom); return;
} else {
Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true>(bp, zoom); return;
Draw<BlitterMode::ColourRemap, ReadMode::WithMargin, BlockType::None, true>(bp, zoom); return;
}
case BlitterMode::Transparent: Draw<BlitterMode::Transparent, RM_NONE, BT_NONE, true>(bp, zoom); return;
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap, RM_NONE, BT_NONE, true>(bp, zoom); return;
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap, RM_NONE, BT_NONE, true>(bp, zoom); return;
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap, RM_NONE, BT_NONE, true>(bp, zoom); return;
case BlitterMode::Transparent: Draw<BlitterMode::Transparent, ReadMode::None, BlockType::None, true>(bp, zoom); return;
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap, ReadMode::None, BlockType::None, true>(bp, zoom); return;
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap, ReadMode::None, BlockType::None, true>(bp, zoom); return;
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap, ReadMode::None, BlockType::None, true>(bp, zoom); return;
}
}
#endif /* FULL_ANIMATION */
+2 -2
View File
@@ -68,7 +68,7 @@ protected:
*/
blitters.insert(Blitters::value_type(this->name, this));
} else {
Debug(driver, 1, "Not registering blitter {} as it is not usable", name);
Debug(Facility::Driver, Severity::Error, "Not registering blitter {} as it is not usable", name);
}
}
@@ -102,7 +102,7 @@ public:
GetActiveBlitter() = b->CreateInstance();
Debug(driver, 1, "Successfully {} blitter '{}'", name.empty() ? "probed" : "loaded", GetCurrentBlitter()->GetName());
Debug(Facility::Driver, Severity::Error, "Successfully {} blitter '{}'", name.empty() ? "probed" : "loaded", GetCurrentBlitter()->GetName());
return GetCurrentBlitter();
}
+10 -10
View File
@@ -110,7 +110,7 @@ public:
void DrawWidget(const Rect &r, WidgetID widget) const override
{
if (widget == WID_BEM_MESSAGE) {
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.frametext), STR_MISSING_GRAPHICS_ERROR, TextColour::FromString, SA_CENTER);
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.frametext), STR_MISSING_GRAPHICS_ERROR, TextColour::FromString, {AlignmentH::Centre, AlignmentV::Middle});
}
}
@@ -212,15 +212,15 @@ public:
this->Window::Close();
}
void OnInit() override
{
this->button_size = maxdim(GetStringBoundingBox(STR_MISSING_GRAPHICS_YES_DOWNLOAD), GetStringBoundingBox(STR_MISSING_GRAPHICS_NO_QUIT));
this->button_size.width += WidgetDimensions::scaled.frametext.Horizontal();
this->button_size.height += WidgetDimensions::scaled.frametext.Vertical();
}
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
{
/* We cache the button size. This is safe as no reinit can happen here. */
if (this->button_size.width == 0) {
this->button_size = maxdim(GetStringBoundingBox(STR_MISSING_GRAPHICS_YES_DOWNLOAD), GetStringBoundingBox(STR_MISSING_GRAPHICS_NO_QUIT));
this->button_size.width += WidgetDimensions::scaled.frametext.Horizontal();
this->button_size.height += WidgetDimensions::scaled.frametext.Vertical();
}
switch (widget) {
case WID_BAFD_QUESTION:
/* The question is twice as wide as the buttons, and determine the height based on the width. */
@@ -239,7 +239,7 @@ public:
{
if (widget != WID_BAFD_QUESTION) return;
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.frametext), STR_MISSING_GRAPHICS_SET_MESSAGE, TextColour::FromString, SA_CENTER);
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.frametext), STR_MISSING_GRAPHICS_SET_MESSAGE, TextColour::FromString, {AlignmentH::Centre, AlignmentV::Middle});
}
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
@@ -381,7 +381,7 @@ bool HandleBootstrap()
/* Initialise the font cache. */
InitializeUnicodeGlyphMap();
/* Next "force" finding a suitable non-sprite font as the local font is missing. */
CheckForMissingGlyphs();
CheckForMissingGlyphs(FontSize::Normal);
/* Initialise the palette. The biggest step is 'faking' some recolour sprites.
* This way the mauve and gray colours work and we can show the user interface. */
+4 -3
View File
@@ -43,10 +43,11 @@ struct BridgeSpec {
PaletteID pal; ///< the palette which is used in the GUI
StringID material; ///< the string that contains the bridge description
StringID transport_name[2]; ///< description of the bridge, when built for road or rail
std::vector<std::vector<PalSpriteID>> sprite_table; ///< table of sprites for drawing the bridge
uint8_t flags; ///< bit 0 set: disable drawing of far pillars.
ControlFlags ctrl_flags{}; ///< control flags
BridgeMiddlePillarFlags pillar_flags{}; ///< bridge pillar flags.
uint8_t flags = 0; ///< bit 0 set: disable drawing of far pillars.
ControlFlags ctrl_flags{}; ///< control flags, NewGRF-only
std::vector<std::vector<PalSpriteID>> sprite_table{}; ///< table of sprites for drawing the bridge, NewGRF-only
};
extern BridgeSpec _bridge[MAX_BRIDGES];
+1 -1
View File
@@ -250,7 +250,7 @@ public:
auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->bridges);
for (auto it = first; it != last; ++it) {
const BridgeSpec *b = it->spec;
DrawSpriteIgnorePadding(b->sprite, b->pal, tr.WithWidth(this->icon_width, rtl), SA_HOR_CENTER | SA_BOTTOM);
DrawSpriteIgnorePadding(b->sprite, b->pal, tr.WithWidth(this->icon_width, rtl), {AlignmentH::Centre, AlignmentV::Bottom});
DrawStringMultiLineWithClipping(tr.Indent(this->icon_width + WidgetDimensions::scaled.hsep_normal, rtl), GetBridgeSelectString(*it));
tr = tr.Translate(0, this->resize.step_height);
}
+31 -29
View File
@@ -264,11 +264,8 @@ static bool EnginePowerVsRunningCostSorter(const GUIEngineListItem &a, const GUI
/** Determines order of train engines by capacity. @copydoc GUIList::Sorter */
static bool TrainEngineCapacitySorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
{
const RailVehicleInfo *rvi_a = RailVehInfo(a.engine_id);
const RailVehicleInfo *rvi_b = RailVehInfo(b.engine_id);
int va = GetTotalCapacityOfArticulatedParts(a.engine_id) * (rvi_a->railveh_type == RailVehicleType::Multihead ? 2 : 1);
int vb = GetTotalCapacityOfArticulatedParts(b.engine_id) * (rvi_b->railveh_type == RailVehicleType::Multihead ? 2 : 1);
int va = GetTotalCapacityOfArticulatedParts(a.engine_id);
int vb = GetTotalCapacityOfArticulatedParts(b.engine_id);
int r = va - vb;
/* Use EngineID to sort instead since we want consistent sorting */
@@ -962,7 +959,7 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
const int offset = (rtl ? -circle_width : circle_width) / 2;
const int level_width = rtl ? -WidgetDimensions::scaled.hsep_indent : WidgetDimensions::scaled.hsep_indent;
for (auto it = first; it != last; ++it) {
for (auto it = first; it != last; ++it, ir = ir.Translate(0, step_size)) {
const auto &item = *it;
const Engine *e = Engine::Get(item.engine_id);
@@ -971,6 +968,13 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
bool is_folded = item.flags.Test(EngineDisplayFlag::IsFolded);
bool shaded = item.flags.Test(EngineDisplayFlag::Shaded);
/* Set up clipping area for the row, keeping coordinates relative to the window. */
DrawPixelInfo tmp_dpi;
if (!FillDrawPixelInfo(&tmp_dpi, ir)) continue;
tmp_dpi.left += ir.left;
tmp_dpi.top += ir.top;
AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
Rect textr = ir.Shrink(WidgetDimensions::scaled.matrix);
Rect tr = ir.Indent(indent, rtl);
@@ -989,7 +993,7 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
if (has_variants) {
Rect fr = tr.WithWidth(circle_width, rtl);
DrawSpriteIgnorePadding(is_folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED, PAL_NONE, fr.WithY(textr), SA_CENTER);
DrawSpriteIgnorePadding(is_folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED, PAL_NONE, fr.WithY(textr), {AlignmentH::Centre, AlignmentV::Middle});
}
tr = tr.Indent(circle_width + WidgetDimensions::scaled.hsep_normal, rtl);
@@ -1023,10 +1027,10 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
Rect cr = tr.WithWidth(count_width, !rtl);
tr = tr.Indent(count_width + WidgetDimensions::scaled.hsep_normal, !rtl);
DrawString(cr.left, cr.right, textr.top + small_text_y_offset, GetString(STR_JUST_COMMA, num_engines), TextColour::Black, SA_RIGHT | SA_FORCE, false, FontSize::Small);
DrawString(cr.left, cr.right, textr.top + small_text_y_offset, GetString(STR_JUST_COMMA, num_engines), TextColour::Black, AlignmentH::ForceRight, false, FontSize::Small);
if (EngineHasReplacementForCompany(Company::Get(_local_company), item.engine_id, selected_group)) {
DrawSpriteIgnorePadding(SPR_GROUP_REPLACE_ACTIVE, num_engines == 0 ? PALETTE_CRASH : PAL_NONE, rr, SA_CENTER);
DrawSpriteIgnorePadding(SPR_GROUP_REPLACE_ACTIVE, num_engines == 0 ? PALETTE_CRASH : PAL_NONE, rr, {AlignmentH::Centre, AlignmentV::Middle});
}
}
@@ -1043,24 +1047,24 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
/* Draw the value of the currently selected sort property to the right (or left in RTL), if applicable */
std::string sort_prop_detail;
switch (GetEngineSortNames(type)[sort_criteria]) {
case STR_SORT_BY_ENGINE_ID:
switch (GetEngineSortNames(type)[sort_criteria].base()) {
case STR_SORT_BY_ENGINE_ID.base():
/* No extra interesting info to show in this case */
break;
case STR_SORT_BY_COST:
case STR_SORT_BY_COST.base():
sort_prop_detail = GetString(STR_PURCHASE_SORT_DETAILS_COST, e->GetCost());
break;
case STR_SORT_BY_MAX_SPEED:
case STR_SORT_BY_MAX_SPEED.base():
if (int max_speed = e->GetDisplayMaxSpeed(); max_speed != 0) {
sort_prop_detail = GetString(STR_PURCHASE_SORT_DETAILS_SPEED, PackVelocity(max_speed, Engine::Get(item.engine_id)->type));
}
break;
case STR_SORT_BY_POWER:
case STR_SORT_BY_POWER.base():
if (int power = e->GetPower(); power != 0) {
sort_prop_detail = GetString(STR_PURCHASE_SORT_DETAILS_POWER, power);
}
break;
case STR_SORT_BY_TRACTIVE_EFFORT:
case STR_SORT_BY_TRACTIVE_EFFORT.base():
/* Allow trucks, and allow trains that are not wagons */
if (type == VehicleType::Road || (type == VehicleType::Train && e->VehInfo<RailVehicleInfo>().railveh_type != RailVehicleType::Wagon)) {
auto max_te = e->GetDisplayMaxTractiveEffort();
@@ -1069,35 +1073,35 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
}
}
break;
case STR_SORT_BY_INTRO_DATE: {
case STR_SORT_BY_INTRO_DATE.base(): {
TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(e->intro_date);
sort_prop_detail = GetString(STR_PURCHASE_SORT_DETAILS_INTRO_DATE, ymd.year);
}
break;
case STR_SORT_BY_NAME:
case STR_SORT_BY_NAME.base():
/* No extra interesting info to show in this case */
break;
case STR_SORT_BY_RUNNING_COST:
case STR_SORT_BY_RUNNING_COST.base():
if (int running_cost = e->GetRunningCost(); running_cost != 0) {
sort_prop_detail = GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_PURCHASE_SORT_DETAILS_RUNNINGCOST_PERIOD : STR_PURCHASE_SORT_DETAILS_RUNNINGCOST_YEAR, running_cost);
}
break;
case STR_SORT_BY_POWER_VS_RUNNING_COST:
case STR_SORT_BY_POWER_VS_RUNNING_COST.base():
/* NOTE: No point showing the actual values of power/running cost, because they are affected by cost factors, which make the math off */
if (Money rc = e->GetRunningCost(); rc != 0) {
sort_prop_detail = GetString(STR_PURCHASE_SORT_DETAILS_POWER_VS_RUNNING_COST, 100 * e->GetPower() / rc, /* digits for DECIMAL */ 2);
}
break;
case STR_SORT_BY_RELIABILITY:
case STR_SORT_BY_RELIABILITY.base():
if (auto isWagon = e->type == VehicleType::Train && e->VehInfo<RailVehicleInfo>().railveh_type == RailVehicleType::Wagon; !isWagon) {
sort_prop_detail = GetString(STR_PURCHASE_SORT_DETAILS_RELIABILITY, ToPercent16(e->reliability));
}
break;
case STR_SORT_BY_CARGO_CAPACITY: {
case STR_SORT_BY_CARGO_CAPACITY.base(): {
uint total_capacity;
switch (type) {
case VehicleType::Train:
total_capacity = GetTotalCapacityOfArticulatedParts(item.engine_id) * (e->VehInfo<RailVehicleInfo>().railveh_type == RailVehicleType::Multihead ? 2 : 1);
total_capacity = GetTotalCapacityOfArticulatedParts(item.engine_id);
break;
case VehicleType::Road:
total_capacity = GetTotalCapacityOfArticulatedParts(item.engine_id);
@@ -1120,7 +1124,7 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
}
}
break;
case STR_SORT_BY_RANGE:
case STR_SORT_BY_RANGE.base():
if (e->type == VehicleType::Aircraft) {
if (uint16_t range = e->GetRange(); range != 0) {
sort_prop_detail = GetString(STR_PURCHASE_SORT_DETAILS_AIRCRAFT_RANGE, range);
@@ -1133,7 +1137,7 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
int sort_detail_width = 0;
if (!sort_prop_detail.empty()) {
DrawString(tr.left, tr.right, textr.top + normal_text_y_offset, sort_prop_detail, tc, SA_RIGHT, false, FontSize::Small);
DrawString(tr.left, tr.right, textr.top + normal_text_y_offset, sort_prop_detail, tc, AlignmentH::End, false, FontSize::Small);
/* If we have sort detail to show, also measure its width so that we can adjust the
* main name drawing rectangle to not overlap. */
@@ -1146,8 +1150,6 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
/* The left/right bounds are adjusted to not overlap with the sort detail that is on the left/right depending on the RTL setting. */
DrawString(tr.left + (rtl ? sort_detail_width : 0), tr.right - (rtl ? 0 : sort_detail_width), textr.top + normal_text_y_offset, name, tc);
ir = ir.Translate(0, step_size);
}
}
@@ -1375,7 +1377,7 @@ struct BuildVehicleWindow : Window {
if (!this->listview_mode) {
/* Query for cost and refitted capacity */
auto [ret, veh_id, refit_capacity, refit_mail, cargo_capacities] = Command<Commands::BuildVehicle>::Do(DoCommandFlag::QueryCost, TileIndex(this->window_number), this->sel_engine, true, cargo, INVALID_CLIENT_ID);
auto [ret, veh_id, refit_capacity, refit_mail, cargo_capacities] = Command<Commands::BuildVehicle>::Do(DoCommandFlag::QueryCost, TileIndex(this->window_number), this->sel_engine, true, cargo, ClientID::Invalid);
if (ret.Succeeded()) {
this->te.cost = ret.GetCost() - e->GetCost();
this->te.capacity = refit_capacity;
@@ -1697,9 +1699,9 @@ struct BuildVehicleWindow : Window {
CargoType cargo = this->cargo_filter_criteria;
if (cargo == CargoFilterCriteria::CF_ANY || cargo == CargoFilterCriteria::CF_ENGINES || cargo == CargoFilterCriteria::CF_NONE) cargo = INVALID_CARGO;
if (this->vehicle_type == VehicleType::Train && RailVehInfo(sel_eng)->railveh_type == RailVehicleType::Wagon) {
Command<Commands::BuildVehicle>::Post(GetCmdBuildVehMsg(this->vehicle_type), CcBuildWagon, TileIndex(this->window_number), sel_eng, true, cargo, INVALID_CLIENT_ID);
Command<Commands::BuildVehicle>::Post(GetCmdBuildVehMsg(this->vehicle_type), CcBuildWagon, TileIndex(this->window_number), sel_eng, true, cargo, ClientID::Invalid);
} else {
Command<Commands::BuildVehicle>::Post(GetCmdBuildVehMsg(this->vehicle_type), CcBuildPrimaryVehicle, TileIndex(this->window_number), sel_eng, true, cargo, INVALID_CLIENT_ID);
Command<Commands::BuildVehicle>::Post(GetCmdBuildVehMsg(this->vehicle_type), CcBuildPrimaryVehicle, TileIndex(this->window_number), sel_eng, true, cargo, ClientID::Invalid);
}
/* Update last used variant in hierarchy and refresh if necessary. */
+15 -15
View File
@@ -37,7 +37,7 @@ void CheckCaches()
{
/* Return here so it is easy to add checks that are run
* always to aid testing of caches. */
if (_debug_desync_level <= 1) return;
if (!IsVisibleSeverity(Facility::Desync, Severity::Warning)) return;
/* Check the town caches. */
std::vector<TownCache> old_town_caches;
@@ -51,7 +51,7 @@ void CheckCaches()
uint i = 0;
for (Town *t : Town::Iterate()) {
if (old_town_caches[i] != t->cache) {
Debug(desync, 2, "warning: town cache mismatch: town {}", t->index);
Debug(Facility::Desync, Severity::Warning, "warning: town cache mismatch: town {}", t->index);
}
i++;
}
@@ -65,7 +65,7 @@ void CheckCaches()
i = 0;
for (const Company *c : Company::Iterate()) {
if (old_infrastructure[i] != c->infrastructure) {
Debug(desync, 2, "warning: infrastructure cache mismatch: company {}", c->index);
Debug(Facility::Desync, Severity::Warning, "warning: infrastructure cache mismatch: company {}", c->index);
}
i++;
}
@@ -115,23 +115,23 @@ void CheckCaches()
for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
FillNewGRFVehicleCache(u);
if (grf_cache[length] != u->grf_cache) {
Debug(desync, 2, "warning: newgrf cache mismatch: type {}, vehicle {}, company {}, unit number {}, wagon {}", v->type, v->index, v->owner, v->unitnumber, length);
Debug(Facility::Desync, Severity::Warning, "warning: newgrf cache mismatch: type {}, vehicle {}, company {}, unit number {}, wagon {}", v->type, v->index, v->owner, v->unitnumber, length);
}
if (veh_cache[length] != u->vcache) {
Debug(desync, 2, "warning: vehicle cache mismatch: type {}, vehicle {}, company {}, unit number {}, wagon {}", v->type, v->index, v->owner, v->unitnumber, length);
Debug(Facility::Desync, Severity::Warning, "warning: vehicle cache mismatch: type {}, vehicle {}, company {}, unit number {}, wagon {}", v->type, v->index, v->owner, v->unitnumber, length);
}
switch (u->type) {
case VehicleType::Train:
if (gro_cache[length] != Train::From(u)->gcache) {
Debug(desync, 2, "warning: train ground vehicle cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
Debug(Facility::Desync, Severity::Warning, "warning: train ground vehicle cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
}
if (tra_cache[length] != Train::From(u)->tcache) {
Debug(desync, 2, "warning: train cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
Debug(Facility::Desync, Severity::Warning, "warning: train cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
}
break;
case VehicleType::Road:
if (gro_cache[length] != RoadVehicle::From(u)->gcache) {
Debug(desync, 2, "warning: road vehicle ground vehicle cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
Debug(Facility::Desync, Severity::Warning, "warning: road vehicle ground vehicle cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
}
break;
default:
@@ -188,11 +188,11 @@ void CheckCaches()
}
UpdateStationDockingTiles(st);
if (ta.tile != st->docking_station.tile || ta.w != st->docking_station.w || ta.h != st->docking_station.h) {
Debug(desync, 2, "warning: station docking mismatch: station {}, company {}", st->index, st->owner);
Debug(Facility::Desync, Severity::Warning, "warning: station docking mismatch: station {}, company {}", st->index, st->owner);
}
for (TileIndex tile : ta) {
if (docking_tiles[tile] != IsDockingTile(tile)) {
Debug(desync, 2, "warning: docking tile mismatch: tile {}", tile);
Debug(Facility::Desync, Severity::Warning, "warning: docking tile mismatch: tile {}", tile);
}
}
}
@@ -203,7 +203,7 @@ void CheckCaches()
i = 0;
for (Station *st : Station::Iterate()) {
if (st->industries_near != old_station_industries_near[i]) {
Debug(desync, 2, "warning: station industries near mismatch: station {}", st->index);
Debug(Facility::Desync, Severity::Warning, "warning: station industries near mismatch: station {}", st->index);
}
i++;
}
@@ -212,14 +212,14 @@ void CheckCaches()
i = 0;
for (Town *t : Town::Iterate()) {
if (t->stations_near != old_town_stations_near[i]) {
Debug(desync, 2, "warning: town stations near mismatch: town {}", t->index);
Debug(Facility::Desync, Severity::Warning, "warning: town stations near mismatch: town {}", t->index);
}
i++;
}
i = 0;
for (Industry *ind : Industry::Iterate()) {
if (ind->stations_near != old_industry_stations_near[i]) {
Debug(desync, 2, "warning: industry stations near mismatch: industry {}", ind->index);
Debug(Facility::Desync, Severity::Warning, "warning: industry stations near mismatch: industry {}", ind->index);
}
i++;
}
@@ -230,13 +230,13 @@ void CheckCaches()
/* Check that the last vehicle is actually last. */
if (v->Last()->Next() != nullptr) {
Debug(desync, 2, "warning: vehicle cache mismatch, last vehicle must not have a next vehicle: type {}, vehicle {}, company {}, unit number {}, invalid 'Last()'", v->type, v->index, v->owner, v->unitnumber);
Debug(Facility::Desync, Severity::Warning, "warning: vehicle cache mismatch, last vehicle must not have a next vehicle: type {}, vehicle {}, company {}, unit number {}, invalid 'Last()'", v->type, v->index, v->owner, v->unitnumber);
}
/* Ensure that all vehicles in the chain have the same last vehicle. */
for (Vehicle *u = v; u != nullptr; u = u->Next()) {
if (u->Last() != v->Last()) {
Debug(desync, 2, "warning: vehicle cache mismatch, all vehicles in chain must have same last vehicle: type {}, vehicle {}, company {}, unit number {}, invalid 'Last()'", v->type, v->index, v->owner, v->unitnumber);
Debug(Facility::Desync, Severity::Warning, "warning: vehicle cache mismatch, all vehicles in chain must have same last vehicle: type {}, vehicle {}, company {}, unit number {}, invalid 'Last()'", v->type, v->index, v->owner, v->unitnumber);
}
}
}
+34 -34
View File
@@ -10,11 +10,11 @@
#ifndef CARGO_TYPE_H
#define CARGO_TYPE_H
#include "core/strong_typedef_type.hpp"
#include "core/label_type.hpp"
#include "core/enum_type.hpp"
/** Globally unique label of a cargo type. */
using CargoLabel = StrongType::Typedef<uint32_t, struct CargoLabelTag, StrongType::Compare>;
using CargoLabel = Label<struct CargoLabelTag>;
/**
* Cargo slots to indicate a cargo type within a game.
@@ -28,48 +28,48 @@ DECLARE_INCREMENT_DECREMENT_OPERATORS(CargoType)
*/
/* Temperate */
static constexpr CargoLabel CT_PASSENGERS{'PASS'};
static constexpr CargoLabel CT_COAL{'COAL'};
static constexpr CargoLabel CT_MAIL{'MAIL'};
static constexpr CargoLabel CT_OIL{'OIL_'};
static constexpr CargoLabel CT_LIVESTOCK{'LVST'};
static constexpr CargoLabel CT_GOODS{'GOOD'};
static constexpr CargoLabel CT_GRAIN{'GRAI'};
static constexpr CargoLabel CT_WOOD{'WOOD'};
static constexpr CargoLabel CT_IRON_ORE{'IORE'};
static constexpr CargoLabel CT_STEEL{'STEL'};
static constexpr CargoLabel CT_VALUABLES{'VALU'};
static constexpr CargoLabel CT_PASSENGERS{"PASS"};
static constexpr CargoLabel CT_COAL{"COAL"};
static constexpr CargoLabel CT_MAIL{"MAIL"};
static constexpr CargoLabel CT_OIL{"OIL_"};
static constexpr CargoLabel CT_LIVESTOCK{"LVST"};
static constexpr CargoLabel CT_GOODS{"GOOD"};
static constexpr CargoLabel CT_GRAIN{"GRAI"};
static constexpr CargoLabel CT_WOOD{"WOOD"};
static constexpr CargoLabel CT_IRON_ORE{"IORE"};
static constexpr CargoLabel CT_STEEL{"STEL"};
static constexpr CargoLabel CT_VALUABLES{"VALU"};
/* Arctic */
static constexpr CargoLabel CT_WHEAT{'WHEA'};
static constexpr CargoLabel CT_PAPER{'PAPR'};
static constexpr CargoLabel CT_GOLD{'GOLD'};
static constexpr CargoLabel CT_FOOD{'FOOD'};
static constexpr CargoLabel CT_WHEAT{"WHEA"};
static constexpr CargoLabel CT_PAPER{"PAPR"};
static constexpr CargoLabel CT_GOLD{"GOLD"};
static constexpr CargoLabel CT_FOOD{"FOOD"};
/* Tropic */
static constexpr CargoLabel CT_RUBBER{'RUBR'};
static constexpr CargoLabel CT_FRUIT{'FRUT'};
static constexpr CargoLabel CT_MAIZE{'MAIZ'};
static constexpr CargoLabel CT_COPPER_ORE{'CORE'};
static constexpr CargoLabel CT_WATER{'WATR'};
static constexpr CargoLabel CT_DIAMONDS{'DIAM'};
static constexpr CargoLabel CT_RUBBER{"RUBR"};
static constexpr CargoLabel CT_FRUIT{"FRUT"};
static constexpr CargoLabel CT_MAIZE{"MAIZ"};
static constexpr CargoLabel CT_COPPER_ORE{"CORE"};
static constexpr CargoLabel CT_WATER{"WATR"};
static constexpr CargoLabel CT_DIAMONDS{"DIAM"};
/* Toyland */
static constexpr CargoLabel CT_SUGAR{'SUGR'};
static constexpr CargoLabel CT_TOYS{'TOYS'};
static constexpr CargoLabel CT_BATTERIES{'BATT'};
static constexpr CargoLabel CT_CANDY{'SWET'};
static constexpr CargoLabel CT_TOFFEE{'TOFF'};
static constexpr CargoLabel CT_COLA{'COLA'};
static constexpr CargoLabel CT_COTTON_CANDY{'CTCD'};
static constexpr CargoLabel CT_BUBBLES{'BUBL'};
static constexpr CargoLabel CT_PLASTIC{'PLST'};
static constexpr CargoLabel CT_FIZZY_DRINKS{'FZDR'};
static constexpr CargoLabel CT_SUGAR{"SUGR"};
static constexpr CargoLabel CT_TOYS{"TOYS"};
static constexpr CargoLabel CT_BATTERIES{"BATT"};
static constexpr CargoLabel CT_CANDY{"SWET"};
static constexpr CargoLabel CT_TOFFEE{"TOFF"};
static constexpr CargoLabel CT_COLA{"COLA"};
static constexpr CargoLabel CT_COTTON_CANDY{"CTCD"};
static constexpr CargoLabel CT_BUBBLES{"BUBL"};
static constexpr CargoLabel CT_PLASTIC{"PLST"};
static constexpr CargoLabel CT_FIZZY_DRINKS{"FZDR"};
/** Dummy label for engines that carry no cargo; they actually carry 0 passengers. */
static constexpr CargoLabel CT_NONE = CT_PASSENGERS;
static constexpr CargoLabel CT_INVALID{UINT32_MAX}; ///< Invalid cargo type.
static constexpr CargoLabel CT_INVALID{"\xFF\xFF\xFF\xFF"}; ///< Invalid cargo type.
static constexpr CargoType NUM_ORIGINAL_CARGO{12}; ///< Original number of cargo types.
static constexpr CargoType NUM_CARGO{64}; ///< Maximum number of cargo types in a game.
+8 -1
View File
@@ -93,7 +93,14 @@ template <>
bool CargoRemoval<VehicleCargoList>::operator()(CargoPacket *cp)
{
uint remove = this->Preprocess(cp);
this->source->RemoveFromMeta(cp, VehicleCargoList::MoveToAction::Keep, remove);
uint remaining = remove;
for (VehicleCargoList::MoveToAction action : {VehicleCargoList::MoveToAction::Keep, VehicleCargoList::MoveToAction::Transfer, VehicleCargoList::MoveToAction::Deliver, VehicleCargoList::MoveToAction::Load}) {
remaining -= this->source->TryRemoveFromMeta(cp, action, remaining);
if (remaining == 0) break;
}
assert(remaining == 0);
return this->Postprocess(cp, remove);
}
+14
View File
@@ -373,6 +373,20 @@ void VehicleCargoList::RemoveFromMeta(const CargoPacket *cp, MoveToAction action
this->AssertCountConsistency();
}
/**
* Try to remove a packet or part of it from the metadata.
* @param cp Packet to be removed.
* @param action MoveToAction of the packet (for updating the counts).
* @param count Amount of cargo to be removed.
* @return Amount of cargo removed.
*/
uint VehicleCargoList::TryRemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count)
{
uint remove = std::min(this->action_counts[action], count);
if (remove > 0) this->RemoveFromMeta(cp, action, remove);
return remove;
}
/**
* Adds a packet to the metadata.
* @param cp Packet to be added.
+2 -1
View File
@@ -18,7 +18,7 @@
#include "source_type.h"
#include "vehicle_type.h"
#include "core/multimap.hpp"
#include "saveload/saveload.h"
#include "saveload/saveload_type.h"
/** Unique identifier for a single cargo packet. */
using CargoPacketID = PoolID<uint32_t, struct CargoPacketIDTag, 0xFFF000, 0xFFFFFF>;
@@ -361,6 +361,7 @@ protected:
void AddToMeta(const CargoPacket *cp, MoveToAction action);
void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count);
uint TryRemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count);
static MoveToAction ChooseAction(const CargoPacket *cp, StationID cargo_next,
StationID current_station, bool accepted, std::span<const StationID> next_station);
+19 -20
View File
@@ -13,7 +13,6 @@
#include "company_base.h"
#include "company_func.h"
#include "currency_func.h"
#include "saveload/saveload.h"
#include "vehicle_base.h"
#include "textbuf_gui.h"
#include "window_gui.h"
@@ -192,7 +191,7 @@ typedef int32_t CheckButtonClick(int32_t new_value, int32_t change_direction);
/** Information of a cheat. */
struct CheatEntry {
VarType type; ///< type of selector
VarMemType type; ///< type of selector
StringID str; ///< string with descriptive text
void *variable; ///< pointer to the variable
bool *been_used; ///< has this cheat been used before?
@@ -204,15 +203,15 @@ struct CheatEntry {
* Order matches with the values of #CheatNumbers
*/
static const CheatEntry _cheats_ui[] = {
{SLE_INT32, STR_CHEAT_MONEY, &_money_cheat_amount, &_cheats.money.been_used, &ClickMoneyCheat },
{SLE_UINT8, STR_CHEAT_CHANGE_COMPANY, &_local_company, &_cheats.switch_company.been_used, &ClickChangeCompanyCheat },
{SLE_BOOL, STR_CHEAT_EXTRA_DYNAMITE, &_cheats.magic_bulldozer.value, &_cheats.magic_bulldozer.been_used, nullptr },
{SLE_BOOL, STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value, &_cheats.crossing_tunnels.been_used, nullptr },
{SLE_BOOL, STR_CHEAT_NO_JETCRASH, &_cheats.no_jetcrash.value, &_cheats.no_jetcrash.been_used, nullptr },
{SLE_BOOL, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, &ClickSetProdCheat },
{SLE_BOOL, STR_CHEAT_STATION_RATING, &_cheats.station_rating.value, &_cheats.station_rating.been_used, nullptr },
{SLE_UINT8, STR_CHEAT_EDIT_MAX_HL, &_settings_game.construction.map_height_limit, &_cheats.edit_max_hl.been_used, &ClickChangeMaxHlCheat },
{SLE_INT32, STR_CHEAT_CHANGE_DATE, &TimerGameCalendar::year, &_cheats.change_date.been_used, &ClickChangeDateCheat },
{ VarMemType::I32, STR_CHEAT_MONEY, &_money_cheat_amount, &_cheats.money.been_used, &ClickMoneyCheat },
{ VarMemType::U8, STR_CHEAT_CHANGE_COMPANY, &_local_company, &_cheats.switch_company.been_used, &ClickChangeCompanyCheat },
{ VarMemType::Bool, STR_CHEAT_EXTRA_DYNAMITE, &_cheats.magic_bulldozer.value, &_cheats.magic_bulldozer.been_used, nullptr },
{ VarMemType::Bool, STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value, &_cheats.crossing_tunnels.been_used, nullptr },
{ VarMemType::Bool, STR_CHEAT_NO_JETCRASH, &_cheats.no_jetcrash.value, &_cheats.no_jetcrash.been_used, nullptr },
{ VarMemType::Bool, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, &ClickSetProdCheat },
{ VarMemType::Bool, STR_CHEAT_STATION_RATING, &_cheats.station_rating.value, &_cheats.station_rating.been_used, nullptr },
{ VarMemType::U8, STR_CHEAT_EDIT_MAX_HL, &_settings_game.construction.map_height_limit, &_cheats.edit_max_hl.been_used, &ClickChangeMaxHlCheat },
{ VarMemType::I32, STR_CHEAT_CHANGE_DATE, &TimerGameCalendar::year, &_cheats.change_date.been_used, &ClickChangeDateCheat },
};
static_assert(CHT_NUM_CHEATS == lengthof(_cheats_ui));
@@ -283,7 +282,7 @@ struct CheatWindow : Window {
std::string str;
switch (ce->type) {
case SLE_BOOL: {
case VarMemType::Bool: {
bool on = (*(bool*)ce->variable);
DrawBoolButton(button_left, y + button_y_offset, Colours::Yellow, Colours::Grey, on, true);
@@ -297,14 +296,14 @@ struct CheatWindow : Window {
/* Draw [<][>] boxes for settings of an integer-type */
DrawArrowButtons(button_left, y + button_y_offset, Colours::Yellow, clicked - (i * 2), true, true);
switch (ce->str) {
switch (ce->str.base()) {
/* Display date for change date cheat */
case STR_CHEAT_CHANGE_DATE:
case STR_CHEAT_CHANGE_DATE.base():
str = GetString(ce->str, TimerGameCalendar::date);
break;
/* Draw coloured flag for change company cheat */
case STR_CHEAT_CHANGE_COMPANY: {
case STR_CHEAT_CHANGE_COMPANY.base(): {
str = GetString(ce->str, val + 1);
uint offset = WidgetDimensions::scaled.hsep_indent + GetStringBoundingBox(str).width;
DrawCompanyIcon(_local_company, rtl ? text_right - offset - WidgetDimensions::scaled.hsep_indent : text_left + offset, y + icon_y_offset);
@@ -380,20 +379,20 @@ struct CheatWindow : Window {
uint width = 0;
for (const auto &ce : _cheats_ui) {
switch (ce.type) {
case SLE_BOOL:
case VarMemType::Bool:
width = std::max(width, GetStringBoundingBox(GetString(ce.str, STR_CONFIG_SETTING_ON)).width);
width = std::max(width, GetStringBoundingBox(GetString(ce.str, STR_CONFIG_SETTING_OFF)).width);
break;
default:
switch (ce.str) {
switch (ce.str.base()) {
/* Display date for change date cheat */
case STR_CHEAT_CHANGE_DATE:
case STR_CHEAT_CHANGE_DATE.base():
width = std::max(width, GetStringBoundingBox(GetString(ce.str, TimerGameCalendar::ConvertYMDToDate(CalendarTime::MAX_YEAR, 11, 31))).width);
break;
/* Draw coloured flag for change company cheat */
case STR_CHEAT_CHANGE_COMPANY:
case STR_CHEAT_CHANGE_COMPANY.base():
width = std::max(width, GetStringBoundingBox(GetString(ce.str, MAX_COMPANIES)).width + WidgetDimensions::scaled.hsep_wide);
break;
@@ -466,7 +465,7 @@ struct CheatWindow : Window {
*ce->been_used = true;
switch (ce->type) {
case SLE_BOOL:
case VarMemType::Bool:
value ^= 1;
if (ce->proc != nullptr) ce->proc(value, 0);
break;
+130 -37
View File
@@ -48,17 +48,31 @@ static CommandCost ClearTile_Clear(TileIndex tile, DoCommandFlags flags)
price.AddCost(_price[clear_price_table[ground]]);
}
if (flags.Test(DoCommandFlag::Execute)) DoClearSquare(tile);
if (flags.Test(DoCommandFlag::Execute)) {
DoClearSquare(tile);
/* We might want to clear to rocks instead of dirt/grass. */
if (flags.Test(DoCommandFlag::ClearToRocks)) MakeClear(tile, ClearGround::Rocks, 3);
}
return price;
}
void DrawClearLandTile(const TileInfo *ti, uint8_t set)
/**
* Draw a ClearGround::Grass tile.
* @param ti The tile to draw.
* @param density The density of the dirt -> grass transition to draw.
*/
void DrawClearLandTile(const TileInfo *ti, uint8_t density)
{
DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh) + set * 19, PAL_NONE);
DrawGroundSprite(_clear_land_sprites_grass[density] + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
}
void DrawHillyLandTile(const TileInfo *ti)
/**
* Draw a ClearGround::Rough tile.
* @param ti The tile to draw.
*/
void DrawRoughLandTile(const TileInfo *ti)
{
if (ti->tileh != SLOPE_FLAT) {
DrawGroundSprite(SPR_FLAT_ROUGH_LAND + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
@@ -67,6 +81,10 @@ void DrawHillyLandTile(const TileInfo *ti)
}
}
/**
* Draw the fences atop a ClearGround::Fields tile.
* @param ti The tile to draw.
*/
static void DrawClearLandFence(const TileInfo *ti)
{
/* combine fences into one sprite object */
@@ -80,7 +98,7 @@ static void DrawClearLandFence(const TileInfo *ti)
if (fence_nw != 0) {
bounds.offset.x = 0;
bounds.offset.y = -static_cast<int>(TILE_SIZE);
bounds.offset.z = GetSlopePixelZInCorner(ti->tileh, CORNER_W);
bounds.offset.z = GetSlopePixelZInCorner(ti->tileh, Corner::W);
SpriteID sprite = _clear_land_fence_sprites[fence_nw - 1] + _fence_mod_by_tileh_nw[ti->tileh];
AddSortableSpriteToDraw(sprite, PAL_NONE, *ti, bounds, false);
}
@@ -89,7 +107,7 @@ static void DrawClearLandFence(const TileInfo *ti)
if (fence_ne != 0) {
bounds.offset.x = -static_cast<int>(TILE_SIZE);
bounds.offset.y = 0;
bounds.offset.z = GetSlopePixelZInCorner(ti->tileh, CORNER_E);
bounds.offset.z = GetSlopePixelZInCorner(ti->tileh, Corner::E);
SpriteID sprite = _clear_land_fence_sprites[fence_ne - 1] + _fence_mod_by_tileh_ne[ti->tileh];
AddSortableSpriteToDraw(sprite, PAL_NONE, *ti, bounds, false);
}
@@ -100,7 +118,7 @@ static void DrawClearLandFence(const TileInfo *ti)
if (fence_sw != 0 || fence_se != 0) {
bounds.offset.x = 0;
bounds.offset.y = 0;
bounds.offset.z = GetSlopePixelZInCorner(ti->tileh, CORNER_S);
bounds.offset.z = GetSlopePixelZInCorner(ti->tileh, Corner::S);
if (fence_sw != 0) {
SpriteID sprite = _clear_land_fence_sprites[fence_sw - 1] + _fence_mod_by_tileh_sw[ti->tileh];
@@ -123,9 +141,7 @@ static void DrawTile_Clear(TileInfo *ti)
uint8_t density = GetClearDensity(ti->tile);
DrawGroundSprite(_clear_land_sprites_snow_desert[density] + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
if (GetClearGround(ti->tile) == ClearGround::Rocks) {
/* There 4 levels of snowy overlay rocks, each with 19 sprites. */
++density;
DrawGroundSprite(SPR_OVERLAY_ROCKS_BASE + (density * 19) + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
DrawGroundSprite(_clear_land_sprites_snowy_rocks[density] + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
}
DrawBridgeMiddle(ti, {});
@@ -138,7 +154,7 @@ static void DrawTile_Clear(TileInfo *ti)
break;
case ClearGround::Rough:
DrawHillyLandTile(ti);
DrawRoughLandTile(ti);
break;
case ClearGround::Rocks:
@@ -328,44 +344,121 @@ static void TileLoop_Clear(TileIndex tile)
MarkTileDirtyByTile(tile);
}
/**
* Test if a tile may have rocks on.
* @param tile The tile index.
* @param allow_water Whether to consider plain water tiles.
* @return true if the tile may have rocks.
*/
static bool TileMayHaveRocks(TileIndex tile, bool allow_water)
{
if (!IsValidTile(tile)) return false;
switch (GetTileType(tile)) {
case TileType::Clear: return true;
case TileType::Water: return IsCoast(tile) || (allow_water && (IsSea(tile) || IsRiver(tile)));
default: return false;
}
}
/**
* Make a tile that may have rocks on have rocks on.
* @param tile The tile index.
*/
static void TileMakeRocks(TileIndex tile)
{
switch (GetTileType(tile)) {
case TileType::Clear:
SetClearGroundDensity(tile, ClearGround::Rocks, 3);
break;
case TileType::Water:
/* Rocks can jump over but not replace rivers. */
if (IsRiver(tile)) return;
SetWaterTileType(tile, IsCoast(tile) ? WaterTileType::CoastRocks : WaterTileType::ClearRocks);
break;
default:
break;
}
}
/**
* Generate a cluster of rocks.
* @param tile Initial tile.
* @param count Number of rocks to attempt to place.
*/
void GenerateRocks(TileIndex tile, uint32_t count)
{
if (!TileMayHaveRocks(tile, false)) return;
for (;;) {
TileMakeRocks(tile);
MarkTileDirtyByTile(tile);
TileIndex tile_new;
do {
if (--count == 0) return;
tile_new = tile + TileOffsByDiagDir(RandomRange(DiagDirection::End));
} while (!TileMayHaveRocks(tile_new, true));
tile = tile_new;
}
}
/**
* Test if a tile may have rough ground on.
* @param tile The tile index.
* @return true if the tile may have rough ground.
*/
static bool TileMayHaveRough(TileIndex tile)
{
return IsTileType(tile, TileType::Clear) && !IsClearGround(tile, ClearGround::Desert);
}
/**
* Generate a cluster of rough ground.
* @param tile Initial tile.
* @param count Number of rough ground tiles to attempt to place.
*/
static void GenerateRough(TileIndex tile, uint32_t count)
{
if (!TileMayHaveRough(tile)) return;
for (;;) {
SetClearGroundDensity(tile, ClearGround::Rough, 3);
MarkTileDirtyByTile(tile);
TileIndex tile_new;
do {
if (--count == 0) return;
tile_new = tile + TileOffsByDiagDir(RandomRange(DiagDirection::End));
} while (!TileMayHaveRough(tile_new));
tile = tile_new;
}
}
/**
* Generate rough and rocky features on clear tiles.
*/
void GenerateClearTile()
{
uint i, gi;
TileIndex tile;
/* add rough tiles */
i = Map::ScaleBySize(GB(Random(), 0, 10) + 0x400);
gi = Map::ScaleBySize(GB(Random(), 0, 7) + 0x80);
uint i = Map::ScaleBySize(GB(Random(), 0, 9) + 0x200);
uint gi = Map::ScaleBySize(GB(Random(), 0, 7) + 0x80);
SetGeneratingWorldProgress(GenWorldProgress::RoughAndRocks, gi + i);
/* Add rough tiles. */
do {
uint32_t r = Random();
IncreaseGeneratingWorldProgress(GenWorldProgress::RoughAndRocks);
tile = RandomTile();
if (IsTileType(tile, TileType::Clear) && !IsClearGround(tile, ClearGround::Desert)) SetClearGroundDensity(tile, ClearGround::Rough, 3);
GenerateRough(RandomTileSeed(r), GB(r, 24, 3) + 1);
} while (--i);
/* add rocky tiles */
/* Add rocky tiles. */
i = gi;
do {
uint32_t r = Random();
tile = RandomTileSeed(r);
IncreaseGeneratingWorldProgress(GenWorldProgress::RoughAndRocks);
if (IsTileType(tile, TileType::Clear)) {
uint j = GB(r, 16, 4) + 5;
for (;;) {
TileIndex tile_new;
SetClearGroundDensity(tile, ClearGround::Rocks, 3);
MarkTileDirtyByTile(tile);
do {
if (--j == 0) goto get_out;
tile_new = tile + TileOffsByDiagDir((DiagDirection)GB(Random(), 0, 2));
} while (!IsTileType(tile_new, TileType::Clear));
tile = tile_new;
}
get_out:;
}
GenerateRocks(RandomTileSeed(r), GB(r, 24, 4) + 5);
} while (--i);
}
+3 -2
View File
@@ -12,7 +12,8 @@
#include "tile_cmd.h"
void DrawHillyLandTile(const TileInfo *ti);
void DrawClearLandTile(const TileInfo *ti, uint8_t set);
void DrawRoughLandTile(const TileInfo *ti);
void DrawClearLandTile(const TileInfo *ti, uint8_t density);
void GenerateRocks(TileIndex tile, uint32_t count);
#endif /* CLEAR_FUNC_H */
+1 -1
View File
@@ -189,7 +189,7 @@ inline void SetFieldType(Tile t, uint f)
inline IndustryID GetIndustryIndexOfField(Tile t)
{
assert(GetClearGround(t) == ClearGround::Fields);
return(IndustryID) t.m2();
return static_cast<IndustryID>(t.m2());
}
/**
+4 -4
View File
@@ -80,10 +80,10 @@ struct CommandInfo {
};
/* Helpers to generate the master command table from the command traits. */
template <typename T>
inline constexpr CommandInfo CommandFromTrait() noexcept { return { T::name, T::flags, T::type }; };
constexpr CommandInfo CommandFromTrait() noexcept { return { T::name, T::flags, T::type }; };
template <typename T, T... i>
inline constexpr auto MakeCommandsFromTraits(std::integer_sequence<T, i...>) noexcept {
constexpr auto MakeCommandsFromTraits(std::integer_sequence<T, i...>) noexcept {
return EnumIndexArray<CommandInfo, Commands, static_cast<Commands>(sizeof...(i))>{{{ CommandFromTrait<CommandTraits<static_cast<Commands>(i)>>()... }}};
}
@@ -259,7 +259,7 @@ void CommandHelperBase::InternalPostResult(CommandCost &res, TileIndex tile, boo
*/
void CommandHelperBase::LogCommandExecution(Commands cmd, StringID err_message, const CommandDataBuffer &args, bool failed)
{
Debug(desync, 1, "{}: {:08x}; {:02x}; {:02x}; {:08x}; {:08x}; {} ({})", failed ? "cmdf" : "cmd", (uint32_t)TimerGameEconomy::date.base(), TimerGameEconomy::date_fract, _current_company, cmd, err_message, FormatArrayAsHex(args), GetCommandName(cmd));
Debug(Facility::Desync, Severity::Error, "{}: {:08x}; {:02x}; {:02x}; {:08x}; {:08x}; {} ({})", failed ? "cmdf" : "cmd", (uint32_t)TimerGameEconomy::date.base(), TimerGameEconomy::date_fract, _current_company, cmd, err_message, FormatArrayAsHex(args), GetCommandName(cmd));
}
/**
@@ -324,7 +324,7 @@ std::tuple<bool, bool, bool> CommandHelperBase::InternalExecuteValidateTestAndPr
BasePersistentStorageArray::SwitchMode(PSM_ENTER_COMMAND);
}
return { false, _debug_desync_level >= 1, send_net };
return { false, IsVisibleSeverity(Facility::Desync, Severity::Error), send_net };
}
/**
+3 -3
View File
@@ -46,7 +46,7 @@ constexpr CommandFlags GetCommandFlags()
* @param cmd_flags Flags from GetCommandFlags
* @return flags for DoCommand
*/
static constexpr inline DoCommandFlags CommandFlagsToDCFlags(CommandFlags cmd_flags)
static constexpr DoCommandFlags CommandFlagsToDCFlags(CommandFlags cmd_flags)
{
DoCommandFlags flags = {};
if (cmd_flags.Test(CommandFlag::NoWater)) flags.Set(DoCommandFlag::NoWater);
@@ -285,7 +285,7 @@ protected:
static inline void SetClientIdHelper([[maybe_unused]] T &data)
{
if constexpr (std::is_same_v<ClientID, T>) {
if (data == INVALID_CLIENT_ID) data = CLIENT_ID_SERVER;
if (data == ClientID::Invalid) data = ClientID::Server;
}
}
@@ -372,7 +372,7 @@ protected:
static inline bool ClientIdIsSet([[maybe_unused]] T &data)
{
if constexpr (std::is_same_v<ClientID, T>) {
return data != INVALID_CLIENT_ID;
return data != ClientID::Invalid;
} else {
return true;
}
+2 -1
View File
@@ -400,6 +400,7 @@ enum class DoCommandFlag : uint8_t {
AllTiles, ///< allow this command also on TileType::Void tiles
NoModifyTownRating, ///< do not change town rating
ForceClearTile, ///< do not only remove the object on the tile, but also clear any water left on it
ClearToRocks, ///< when clearing land, make rocks instead of bare dirt/grass
};
/** Bitset of \c DoCommandFlag elements. */
@@ -483,7 +484,7 @@ template <Commands Tcmd> struct CommandTraits;
static constexpr auto &proc = proc_; \
static constexpr CommandFlags flags = flags_; \
static constexpr CommandType type = type_; \
static inline constexpr std::string_view name = #proc_; \
static constexpr std::string_view name = #proc_; \
};
/** Storage buffer for serialized command data. */
+87 -59
View File
@@ -37,12 +37,14 @@
#include "goal_base.h"
#include "story_base.h"
#include "company_cmd.h"
#include "script/api/script_event_types.hpp"
#include "timer/timer.h"
#include "timer/timer_game_economy.h"
#include "timer/timer_game_tick.h"
#include "timer/timer_window.h"
#include "road_gui.h"
#include "widgets/company_widget.h"
#include "widgets/statusbar_widget.h"
#include "table/strings.h"
@@ -428,6 +430,44 @@ CommandCost CheckTileOwnership(TileIndex tile)
return CheckOwnership(GetTileOwner(tile), tile);
}
/**
* Set a company name based on type and seed, if the name is unique and shorter than the max length.
* @param other_names List of names that cannot be used.
* @param c The company of the name to set.
* @param t The nearby town, for news message.
* @param str The type of name.
* @param strp The random seed.
* @return True iff the name was set.
*/
static bool SetCompanyName(std::span<const std::string> other_names, Company *c, const Town *t, StringID str, uint32_t strp)
{
assert(c != nullptr);
assert(t != nullptr);
/* Name must not be too long. */
std::string name = GetString(str, strp);
if (Utf8StringLength(name) >= MAX_LENGTH_COMPANY_NAME_CHARS) return false;
/* No companies must have this name already. */
if (std::ranges::find(other_names, name) != other_names.end()) return false;
c->name_1 = str;
c->name_2 = strp;
MarkWholeScreenDirty();
AI::BroadcastNewEvent(new ScriptEventCompanyRenamed(c->index, name));
Game::NewEvent(new ScriptEventCompanyRenamed(c->index, name));
if (!c->is_ai) return true;
auto cni = std::make_unique<CompanyNewsInformation>(STR_NEWS_COMPANY_LAUNCH_TITLE, c);
EncodedString headline = GetEncodedString(STR_NEWS_COMPANY_LAUNCH_DESCRIPTION, cni->company_name, t->index);
AddNewsItem(std::move(headline),
NewsType::CompanyInfo, NewsStyle::Company, {}, c->last_build_coordinate, {}, std::move(cni));
return true;
}
/**
* Generate the name of a company from the last build coordinate.
* @param c Company to give a name.
@@ -437,51 +477,24 @@ static void GenerateCompanyName(Company *c)
if (c->name_1 != STR_SV_UNNAMED) return;
if (c->last_build_coordinate == 0) return;
Town *t = ClosestTownFromTile(c->last_build_coordinate, UINT_MAX);
/* Collect existing company names. */
std::vector<std::string> other_names;
for (const Company *cc : Company::Iterate()) {
if (cc != c) other_names.emplace_back(GetString(STR_COMPANY_NAME, cc->index));
}
StringID str;
uint32_t strp;
std::string name;
const Town *t = ClosestTownFromTile(c->last_build_coordinate, UINT_MAX);
if (t->name.empty() && IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_END)) {
str = t->townnametype - SPECSTR_TOWNNAME_START + SPECSTR_COMPANY_NAME_START;
strp = t->townnameparts;
verify_name:;
/* No companies must have this name already */
for (const Company *cc : Company::Iterate()) {
if (cc->name_1 == str && cc->name_2 == strp) goto bad_town_name;
}
name = GetString(str, strp);
if (Utf8StringLength(name) >= MAX_LENGTH_COMPANY_NAME_CHARS) goto bad_town_name;
set_name:;
c->name_1 = str;
c->name_2 = strp;
MarkWholeScreenDirty();
AI::BroadcastNewEvent(new ScriptEventCompanyRenamed(c->index, name));
Game::NewEvent(new ScriptEventCompanyRenamed(c->index, name));
if (c->is_ai) {
auto cni = std::make_unique<CompanyNewsInformation>(STR_NEWS_COMPANY_LAUNCH_TITLE, c);
EncodedString headline = GetEncodedString(STR_NEWS_COMPANY_LAUNCH_DESCRIPTION, cni->company_name, t->index);
AddNewsItem(std::move(headline),
NewsType::CompanyInfo, NewsStyle::Company, {}, c->last_build_coordinate, {}, std::move(cni));
}
return;
if (SetCompanyName(other_names, c, t, SPECSTR_COMPANY_NAME_START + (t->townnametype - SPECSTR_TOWNNAME_START), t->townnameparts)) return;
}
bad_town_name:;
if (c->president_name_1 == SPECSTR_PRESIDENT_NAME) {
str = SPECSTR_ANDCO_NAME;
strp = c->president_name_2;
name = GetString(str, strp);
goto set_name;
} else {
str = SPECSTR_ANDCO_NAME;
strp = Random();
goto verify_name;
if (SetCompanyName(other_names, c, t, SPECSTR_ANDCO_NAME, c->president_name_2)) return;
}
for (;;) {
if (SetCompanyName(other_names, c, t, SPECSTR_ANDCO_NAME, Random())) return;
}
}
@@ -524,7 +537,7 @@ static Colours GenerateCompanyColour()
}
/* Sort it according to the values in _colour_sort. */
std::ranges::stable_sort(colours, {}, [](auto &i) { return _colour_sort[i]; });
std::ranges::stable_sort(colours, std::greater_equal{}, [](auto &i) { return _colour_sort[i]; });
/* Move the colours that look similar to each company's colour to the side */
for (const Company *c : Company::Iterate()) {
@@ -541,29 +554,44 @@ static Colours GenerateCompanyColour()
return colours.at(0);
}
/**
* Set a company's president name based on seed, if the name is unique and shorter than the max length.
* @param other_names List of names that cannot be used.
* @param c The company of the president name to set.
* @param seed The random seed.
* @return True iff the name was set.
*/
static bool SetPresidentName(std::span<const std::string> other_names, Company *c, uint32_t seed)
{
assert(c != nullptr);
c->president_name_1 = SPECSTR_PRESIDENT_NAME;
c->president_name_2 = seed;
/* President name must not be too long. */
std::string name = GetString(STR_PRESIDENT_NAME, c->index);
if (Utf8StringLength(name) >= MAX_LENGTH_PRESIDENT_NAME_CHARS) return false;
/* No presidents must have this name already. */
if (std::ranges::find(other_names, name) != other_names.end()) return false;
return true;
}
/**
* Generate a random president name of a company.
* @param c Company that needs a new president name.
*/
static void GeneratePresidentName(Company *c)
{
/* Collect existing president names. */
std::vector<std::string> other_names;
for (const Company *cc : Company::Iterate()) {
if (cc != c) other_names.emplace_back(GetString(STR_PRESIDENT_NAME, cc->index));
}
for (;;) {
restart:;
c->president_name_2 = Random();
c->president_name_1 = SPECSTR_PRESIDENT_NAME;
/* Reserve space for extra unicode character. We need to do this to be able
* to detect too long president name. */
std::string name = GetString(STR_PRESIDENT_NAME, c->index);
if (Utf8StringLength(name) >= MAX_LENGTH_PRESIDENT_NAME_CHARS) continue;
for (const Company *cc : Company::Iterate()) {
if (c != cc) {
std::string other_name = GetString(STR_PRESIDENT_NAME, cc->index);
if (name == other_name) goto restart;
}
}
return;
if (SetPresidentName(other_names, c, Random())) return;
}
}
@@ -671,7 +699,7 @@ TimeoutTimer<TimerGameTick> _new_competitor_timeout({ TimerGameTick::Priority::C
/* Send a command to all clients to start up a new AI.
* Works fine for Multiplayer and Singleplayer */
Command<Commands::CompanyControl>::Post(CompanyCtrlAction::NewAI, CompanyID::Invalid(), CompanyRemoveReason::None, INVALID_CLIENT_ID);
Command<Commands::CompanyControl>::Post(CompanyCtrlAction::NewAI, CompanyID::Invalid(), CompanyRemoveReason::None, ClientID::Invalid);
});
/** Start of a new game. */
@@ -792,7 +820,7 @@ void OnTick_Companies()
for (auto i = 0; i < _settings_game.difficulty.max_no_competitors; i++) {
if (_networking && num_companies++ >= _settings_client.network.max_companies) break;
if (num_ais++ >= _settings_game.difficulty.max_no_competitors) break;
Command<Commands::CompanyControl>::Post(CompanyCtrlAction::NewAI, CompanyID::Invalid(), {}, INVALID_CLIENT_ID);
Command<Commands::CompanyControl>::Post(CompanyCtrlAction::NewAI, CompanyID::Invalid(), {}, ClientID::Invalid);
}
timeout = 10 * 60 * Ticks::TICKS_PER_SECOND;
}
+1 -1
View File
@@ -14,7 +14,7 @@
#include "company_type.h"
#include "livery.h"
enum ClientID : uint32_t;
enum class ClientID : uint32_t;
enum class Colours : uint8_t;
CommandCost CmdCompanyCtrl(DoCommandFlags flags, CompanyCtrlAction cca, CompanyID company_id, CompanyRemoveReason reason, ClientID client_id);
+18 -18
View File
@@ -188,12 +188,12 @@ static void DrawCategories(const Rect &r)
{
int y = r.top;
/* Draw description of 12-minute economic period. */
DrawString(r.left, r.right, y, (TimerGameEconomy::UsingWallclockUnits() ? STR_FINANCES_PERIOD_CAPTION : STR_FINANCES_YEAR_CAPTION), TextColour::FromString, SA_LEFT, true);
DrawString(r.left, r.right, y, (TimerGameEconomy::UsingWallclockUnits() ? STR_FINANCES_PERIOD_CAPTION : STR_FINANCES_YEAR_CAPTION), TextColour::FromString, AlignmentH::Start, true);
y += GetCharacterHeight(FontSize::Normal) + WidgetDimensions::scaled.vsep_wide;
for (const ExpensesList &list : _expenses_list_types) {
/* Draw category title and advance y */
DrawString(r.left, r.right, y, list.title, TextColour::FromString, SA_LEFT);
DrawString(r.left, r.right, y, list.title, TextColour::FromString, AlignmentH::Start);
y += GetCharacterHeight(FontSize::Normal);
/* Draw category items and advance y */
@@ -204,7 +204,7 @@ static void DrawCategories(const Rect &r)
y += WidgetDimensions::scaled.vsep_normal;
/* Draw category total and advance y */
DrawString(r.left, r.right, y, STR_FINANCES_TOTAL_CAPTION, TextColour::FromString, SA_RIGHT);
DrawString(r.left, r.right, y, STR_FINANCES_TOTAL_CAPTION, TextColour::FromString, AlignmentH::End);
y += GetCharacterHeight(FontSize::Normal);
/* Advance y by a blockspace after this category block */
@@ -213,7 +213,7 @@ static void DrawCategories(const Rect &r)
/* Draw total profit/loss */
y += WidgetDimensions::scaled.vsep_normal;
DrawString(r.left, r.right, y, STR_FINANCES_PROFIT, TextColour::FromString, SA_LEFT);
DrawString(r.left, r.right, y, STR_FINANCES_PROFIT, TextColour::FromString, AlignmentH::Start);
}
/**
@@ -233,7 +233,7 @@ static void DrawPrice(Money amount, int left, int right, int top, TextColour col
amount = -amount;
str = STR_FINANCES_POSITIVE_INCOME;
}
DrawString(left, right, top, GetString(str, amount), colour, SA_RIGHT | SA_FORCE);
DrawString(left, right, top, GetString(str, amount), colour, AlignmentH::ForceRight);
}
/**
@@ -279,7 +279,7 @@ static void DrawYearColumn(const Rect &r, TimerGameEconomy::Year year, const Exp
Money sum;
/* Year header */
DrawString(r.left, r.right, y, GetString(STR_FINANCES_YEAR, year), TextColour::FromString, SA_RIGHT | SA_FORCE, true);
DrawString(r.left, r.right, y, GetString(STR_FINANCES_YEAR, year), TextColour::FromString, AlignmentH::ForceRight, true);
y += GetCharacterHeight(FontSize::Normal) + WidgetDimensions::scaled.vsep_wide;
/* Categories */
@@ -322,10 +322,10 @@ static constexpr std::initializer_list<NWidgetPart> _nested_company_finances_wid
NWidget(WWT_TEXT, Colours::Invalid), SetStringTip(STR_FINANCES_BANK_BALANCE_TITLE), SetPadding(WidgetDimensions::unscaled.vsep_normal, 0, 0, 0),
EndContainer(),
NWidget(NWID_VERTICAL), // Vertical column with bank balance amount, loan amount, and total.
NWidget(WWT_TEXT, Colours::Invalid, WID_CF_OWN_VALUE), SetAlignment(SA_VERT_CENTER | SA_RIGHT | SA_FORCE),
NWidget(WWT_TEXT, Colours::Invalid, WID_CF_LOAN_VALUE), SetAlignment(SA_VERT_CENTER | SA_RIGHT | SA_FORCE),
NWidget(WWT_TEXT, Colours::Invalid, WID_CF_OWN_VALUE), SetAlignment({AlignmentH::ForceRight, AlignmentV::Middle}),
NWidget(WWT_TEXT, Colours::Invalid, WID_CF_LOAN_VALUE), SetAlignment({AlignmentH::ForceRight, AlignmentV::Middle}),
NWidget(WWT_EMPTY, Colours::Invalid, WID_CF_BALANCE_LINE), SetMinimalSize(0, WidgetDimensions::unscaled.vsep_normal),
NWidget(WWT_TEXT, Colours::Invalid, WID_CF_BALANCE_VALUE), SetAlignment(SA_VERT_CENTER | SA_RIGHT | SA_FORCE),
NWidget(WWT_TEXT, Colours::Invalid, WID_CF_BALANCE_VALUE), SetAlignment({AlignmentH::ForceRight, AlignmentV::Middle}),
EndContainer(),
NWidget(NWID_SELECTION, Colours::Invalid, WID_CF_SEL_MAXLOAN),
NWidget(NWID_VERTICAL), SetPIPRatio(0, 0, 1), // Max loan information
@@ -1794,14 +1794,14 @@ struct CompanyInfrastructureWindow : Window
case InfrastructureItemType::Total:
/* Draw line in the spacer above the total. */
GfxFillRect(costr.Translate(0, -WidgetDimensions::scaled.vsep_normal).WithHeight(WidgetDimensions::scaled.fullbevel.top), PC_WHITE);
DrawString(costr, GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, it->cost * 12), TextColour::Black, SA_RIGHT | SA_FORCE);
DrawString(costr, GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, it->cost * 12), TextColour::Black, AlignmentH::ForceRight);
break;
case InfrastructureItemType::Value:
DrawString(labelr.Indent(WidgetDimensions::scaled.hsep_indent, rtl), GetString(it->label), TextColour::White);
DrawString(countr, GetString(STR_JUST_COMMA, it->count), TextColour::White, SA_RIGHT | SA_FORCE);
DrawString(countr, GetString(STR_JUST_COMMA, it->count), TextColour::White, AlignmentH::ForceRight);
if (_settings_game.economy.infrastructure_maintenance) {
DrawString(costr, GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, it->cost * 12), TextColour::Black, SA_RIGHT | SA_FORCE);
DrawString(costr, GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, it->cost * 12), TextColour::Black, AlignmentH::ForceRight);
}
break;
}
@@ -1875,7 +1875,7 @@ static constexpr std::initializer_list<NWidgetPart> _nested_company_widgets = {
NWidget(WWT_EMPTY, Colours::Invalid, WID_C_DESC_COLOUR_SCHEME_EXAMPLE), SetMinimalSize(30, 0), SetFill(1, 1),
EndContainer(),
NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0),
NWidget(WWT_TEXT, Colours::Invalid, WID_C_DESC_VEHICLE), SetStringTip(STR_COMPANY_VIEW_VEHICLES_TITLE), SetAlignment(SA_LEFT | SA_TOP),
NWidget(WWT_TEXT, Colours::Invalid, WID_C_DESC_VEHICLE), SetStringTip(STR_COMPANY_VIEW_VEHICLES_TITLE), SetAlignment({AlignmentH::Start, AlignmentV::Top}),
NWidget(WWT_EMPTY, Colours::Invalid, WID_C_DESC_VEHICLE_COUNTS), SetMinimalTextLines(4, 0), SetFill(1, 1),
EndContainer(),
EndContainer(),
@@ -1894,7 +1894,7 @@ static constexpr std::initializer_list<NWidgetPart> _nested_company_widgets = {
NWidget(WWT_TEXT, Colours::Invalid, WID_C_DESC_COMPANY_VALUE), SetFill(1, 0),
NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0),
NWidget(WWT_TEXT, Colours::Invalid, WID_C_DESC_INFRASTRUCTURE), SetStringTip(STR_COMPANY_VIEW_INFRASTRUCTURE), SetAlignment(SA_LEFT | SA_TOP),
NWidget(WWT_TEXT, Colours::Invalid, WID_C_DESC_INFRASTRUCTURE), SetStringTip(STR_COMPANY_VIEW_INFRASTRUCTURE), SetAlignment({AlignmentH::Start, AlignmentV::Top}),
NWidget(WWT_EMPTY, Colours::Invalid, WID_C_DESC_INFRASTRUCTURE_COUNTS), SetMinimalTextLines(5, 0), SetFill(1, 0),
NWidget(NWID_VERTICAL), SetPIPRatio(0, 0, 1),
NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_C_VIEW_INFRASTRUCTURE), SetStringTip(STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON, STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP),
@@ -2021,7 +2021,7 @@ struct CompanyWindow : Window
break;
case WID_C_DESC_VEHICLE_COUNTS: {
uint64_t max_value = GetParamMaxValue(5000); // Maximum number of vehicles
uint64_t max_value = GetParamMaxValue(10000); // Maximum number of vehicles
for (const auto &count_string : _company_view_vehicle_count_strings) {
size.width = std::max(size.width, GetStringBoundingBox(GetString(count_string, max_value)).width + padding.width);
}
@@ -2123,7 +2123,7 @@ struct CompanyWindow : Window
break;
case WID_C_FACE_TITLE:
DrawStringMultiLine(r, GetString(STR_COMPANY_VIEW_PRESIDENT_MANAGER_TITLE, c->index), TextColour::FromString, SA_HOR_CENTER);
DrawStringMultiLine(r, GetString(STR_COMPANY_VIEW_PRESIDENT_MANAGER_TITLE, c->index), TextColour::FromString, AlignmentH::Centre);
break;
case WID_C_DESC_COLOUR_SCHEME_EXAMPLE: {
@@ -2244,7 +2244,7 @@ struct CompanyWindow : Window
this->query_widget = WID_C_COMPANY_JOIN;
CompanyID company = this->window_number;
if (_network_server) {
NetworkServerDoMove(CLIENT_ID_SERVER, company);
NetworkServerDoMove(ClientID::Server, company);
MarkWholeScreenDirty();
} else {
/* just send the join command */
@@ -2389,7 +2389,7 @@ struct BuyCompanyWindow : Window {
case WID_BC_QUESTION: {
const Company *c = Company::Get(this->window_number);
DrawStringMultiLine(r, GetString(this->hostile_takeover ? STR_BUY_COMPANY_HOSTILE_TAKEOVER : STR_BUY_COMPANY_MESSAGE, c->index, this->company_value), TextColour::FromString, SA_CENTER);
DrawStringMultiLine(r, GetString(this->hostile_takeover ? STR_BUY_COMPANY_HOSTILE_TAKEOVER : STR_BUY_COMPANY_MESSAGE, c->index, this->company_value), TextColour::FromString, {AlignmentH::Centre, AlignmentV::Middle});
break;
}
}
+1 -3
View File
@@ -16,8 +16,6 @@
#include "company_type.h"
#include "gfx_type.h"
#include "table/strings.h"
/** Ways a FaceVar should be interpreted. */
enum class FaceVarType : uint8_t {
Sprite, ///< FaceVar describes an offset to the given SpriteID.
@@ -33,7 +31,7 @@ struct FaceVar {
uint8_t length; ///< Number of bits used in the CompanyManagerFace
uint8_t valid_values; ///< The number of valid values
std::variant<SpriteID, uint64_t, std::pair<uint64_t, uint64_t>> data; ///< The first sprite
StringID name = STR_NULL; ///< Name of the configurable component of the face.
StringID name{}; ///< Name of the configurable component of the face.
/**
* Gets the company manager's face bits.
+5 -5
View File
@@ -40,7 +40,7 @@ std::optional<FileHandle> _iconsole_output_file;
void IConsoleInit()
{
_iconsole_output_file = std::nullopt;
_redirect_console_to_client = INVALID_CLIENT_ID;
_redirect_console_to_client = ClientID::Invalid;
_redirect_console_to_admin = AdminID::Invalid();
IConsoleGUIInit();
@@ -91,7 +91,7 @@ void IConsolePrint(ExtendedTextColour colour_code, const std::string &string)
{
assert(IsValidConsoleColour(colour_code));
if (_redirect_console_to_client != INVALID_CLIENT_ID) {
if (_redirect_console_to_client != ClientID::Invalid) {
/* Redirect the string to the client */
NetworkServerSendRcon(_redirect_console_to_client, colour_code, string);
return;
@@ -184,7 +184,7 @@ static std::string RemoveUnderscores(std::string name)
*/
static void IConsoleAliasExec(const IConsoleAlias *alias, std::span<std::string> tokens, uint recurse_count)
{
Debug(console, 6, "Requested command is an alias; parsing...");
Debug(Facility::Console, Severity::Debug2, "Requested command is an alias; parsing...");
if (recurse_count > ICON_MAX_RECURSE) {
IConsolePrint(CC_ERROR, "Too many alias expansions, recursion limit reached.");
@@ -272,7 +272,7 @@ void IConsoleCmdExec(std::string_view command_string, const uint recurse_count)
{
if (command_string[0] == '#') return; // comments
Debug(console, 4, "Executing cmdline: '{}'", command_string);
Debug(Facility::Console, Severity::Info, "Executing cmdline: '{}'", command_string);
std::string buffer;
StringBuilder builder{buffer};
@@ -331,7 +331,7 @@ void IConsoleCmdExec(std::string_view command_string, const uint recurse_count)
}
for (size_t i = 0; i < tokens.size(); i++) {
Debug(console, 8, "Token {} is: '{}'", i, tokens[i]);
Debug(Facility::Console, Severity::Trace2, "Token {} is: '{}'", i, tokens[i]);
}
if (tokens.empty() || tokens[0].empty()) return; // don't execute empty commands
+39 -54
View File
@@ -13,7 +13,7 @@
#include "debug.h"
#include "engine_func.h"
#include "landscape.h"
#include "saveload/saveload.h"
#include "saveload/saveload_func.h"
#include "network/core/network_game_info.h"
#include "network/network.h"
#include "network/network_func.h"
@@ -27,6 +27,7 @@
#include "fontcache.h"
#include "screenshot.h"
#include "genworld.h"
#include "string_func.h"
#include "strings_func.h"
#include "viewport_func.h"
#include "window_func.h"
@@ -698,7 +699,7 @@ static bool ConKickOrBan(std::string_view arg, bool ban, std::string_view reason
* kicking frees closes and subsequently free the connection related instances, which we
* would be reading from and writing to after returning. So we would read or write data
* from freed memory up till the segfault triggers. */
if (*client_id == CLIENT_ID_SERVER || *client_id == _redirect_console_to_client) {
if (*client_id == ClientID::Server || *client_id == _redirect_console_to_client) {
IConsolePrint(CC_ERROR, "You can not {} yourself!", ban ? "ban" : "kick");
return true;
}
@@ -945,7 +946,7 @@ static bool ConClientNickChange(std::span<std::string_view> argv)
return true;
}
if (*client_id == CLIENT_ID_SERVER) {
if (*client_id == ClientID::Server) {
IConsolePrint(CC_ERROR, "Please use the command 'name' to change your own name!");
return true;
}
@@ -1024,7 +1025,7 @@ static bool ConJoinCompany(std::span<std::string_view> argv)
/* non-dedicated server may just do the move! */
if (_network_server) {
NetworkServerDoMove(CLIENT_ID_SERVER, *company_id);
NetworkServerDoMove(ClientID::Server, *company_id);
} else {
NetworkClientRequestMove(*company_id);
}
@@ -1070,7 +1071,7 @@ static bool ConMoveClient(std::span<std::string_view> argv)
return true;
}
if (ci->client_id == CLIENT_ID_SERVER && _network_dedicated) {
if (ci->client_id == ClientID::Server && _network_dedicated) {
IConsolePrint(CC_ERROR, "You cannot move the server!");
return true;
}
@@ -1118,7 +1119,7 @@ static bool ConResetCompany(std::span<std::string_view> argv)
IConsolePrint(CC_ERROR, "Cannot remove company: a client is connected to that company.");
return false;
}
const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(ClientID::Server);
assert(ci != nullptr);
if (ci->client_playas == *index) {
IConsolePrint(CC_ERROR, "Cannot remove company: the server is connected to that company.");
@@ -1126,7 +1127,7 @@ static bool ConResetCompany(std::span<std::string_view> argv)
}
/* It is safe to remove this company */
Command<Commands::CompanyControl>::Post(CompanyCtrlAction::Delete, *index, CompanyRemoveReason::Manual, INVALID_CLIENT_ID);
Command<Commands::CompanyControl>::Post(CompanyCtrlAction::Delete, *index, CompanyRemoveReason::Manual, ClientID::Invalid);
IConsolePrint(CC_DEFAULT, "Company deleted.");
return true;
@@ -1563,7 +1564,7 @@ static bool ConStartAI(std::span<std::string_view> argv)
}
/* Start a new AI company */
Command<Commands::CompanyControl>::Post(CompanyCtrlAction::NewAI, CompanyID::Invalid(), CompanyRemoveReason::None, INVALID_CLIENT_ID);
Command<Commands::CompanyControl>::Post(CompanyCtrlAction::NewAI, CompanyID::Invalid(), CompanyRemoveReason::None, ClientID::Invalid);
return true;
}
@@ -1605,8 +1606,8 @@ static bool ConReloadAI(std::span<std::string_view> argv)
}
/* First kill the company of the AI, then start a new one. This should start the current AI again */
Command<Commands::CompanyControl>::Post(CompanyCtrlAction::Delete, *company_id, CompanyRemoveReason::Manual, INVALID_CLIENT_ID);
Command<Commands::CompanyControl>::Post(CompanyCtrlAction::NewAI, *company_id, CompanyRemoveReason::None, INVALID_CLIENT_ID);
Command<Commands::CompanyControl>::Post(CompanyCtrlAction::Delete, *company_id, CompanyRemoveReason::Manual, ClientID::Invalid);
Command<Commands::CompanyControl>::Post(CompanyCtrlAction::NewAI, *company_id, CompanyRemoveReason::None, ClientID::Invalid);
IConsolePrint(CC_DEFAULT, "AI reloaded.");
return true;
@@ -1649,7 +1650,7 @@ static bool ConStopAI(std::span<std::string_view> argv)
}
/* Now kill the company of the AI. */
Command<Commands::CompanyControl>::Post(CompanyCtrlAction::Delete, *company_id, CompanyRemoveReason::Manual, INVALID_CLIENT_ID);
Command<Commands::CompanyControl>::Post(CompanyCtrlAction::Delete, *company_id, CompanyRemoveReason::Manual, ClientID::Invalid);
IConsolePrint(CC_DEFAULT, "AI stopped, company deleted.");
return true;
@@ -2050,7 +2051,7 @@ static bool ConSay(std::span<std::string_view> argv)
NetworkClientSendChat(NetworkAction::ChatBroadcast, NetworkChatDestinationType::Broadcast, 0 /* param does not matter */, argv[1]);
} else {
bool from_admin = (_redirect_console_to_admin < AdminID::Invalid());
NetworkServerSendChat(NetworkAction::ChatBroadcast, NetworkChatDestinationType::Broadcast, 0, argv[1], CLIENT_ID_SERVER, from_admin);
NetworkServerSendChat(NetworkAction::ChatBroadcast, NetworkChatDestinationType::Broadcast, 0, argv[1], ClientID::Server, from_admin);
}
return true;
@@ -2082,7 +2083,7 @@ static bool ConSayCompany(std::span<std::string_view> argv)
NetworkClientSendChat(NetworkAction::ChatTeam, NetworkChatDestinationType::Team, company_id->base(), argv[2]);
} else {
bool from_admin = (_redirect_console_to_admin < AdminID::Invalid());
NetworkServerSendChat(NetworkAction::ChatTeam, NetworkChatDestinationType::Team, company_id->base(), argv[2], CLIENT_ID_SERVER, from_admin);
NetworkServerSendChat(NetworkAction::ChatTeam, NetworkChatDestinationType::Team, company_id->base(), argv[2], ClientID::Server, from_admin);
}
return true;
@@ -2106,10 +2107,10 @@ static bool ConSayClient(std::span<std::string_view> argv)
}
if (!_network_server) {
NetworkClientSendChat(NetworkAction::ChatClient, NetworkChatDestinationType::Client, *client_id, argv[2]);
NetworkClientSendChat(NetworkAction::ChatClient, NetworkChatDestinationType::Client, to_underlying(*client_id), argv[2]);
} else {
bool from_admin = (_redirect_console_to_admin < AdminID::Invalid());
NetworkServerSendChat(NetworkAction::ChatClient, NetworkChatDestinationType::Client, *client_id, argv[2], CLIENT_ID_SERVER, from_admin);
NetworkServerSendChat(NetworkAction::ChatClient, NetworkChatDestinationType::Client, to_underlying(*client_id), argv[2], ClientID::Server, from_admin);
}
return true;
@@ -2657,7 +2658,7 @@ static bool ConNewGRFProfile(std::span<std::string_view> argv)
bool active = selected && profiler->active;
TextColour tc = active ? TextColour::LightBlue : selected ? TextColour::Green : CC_INFO;
std::string_view statustext = active ? " (active)" : selected ? " (selected)" : "";
IConsolePrint(tc, "{}: [{:08X}] {}{}", i, std::byteswap(grf.grfid), grf.filename, statustext);
IConsolePrint(tc, "{}: [{}] {}{}", i, FormatArrayAsHex(grf.grfid), grf.filename, statustext);
i++;
}
return true;
@@ -2673,7 +2674,7 @@ static bool ConNewGRFProfile(std::span<std::string_view> argv)
}
const GRFFile *grf = &files[*grfnum - 1];
if (std::any_of(_newgrf_profilers.begin(), _newgrf_profilers.end(), [&](NewGRFProfiler &pr) { return pr.grffile == grf; })) {
IConsolePrint(CC_WARNING, "GRF number {} [{:08X}] is already selected for profiling.", *grfnum, std::byteswap(grf->grfid));
IConsolePrint(CC_WARNING, "GRF number {} [{}] is already selected for profiling.", *grfnum, FormatArrayAsHex(grf->grfid));
continue;
}
_newgrf_profilers.emplace_back(grf);
@@ -2709,7 +2710,7 @@ static bool ConNewGRFProfile(std::span<std::string_view> argv)
started++;
if (!grfids.empty()) grfids += ", ";
format_append(grfids, "[{:08X}]", std::byteswap(pr.grffile->grfid));
format_append(grfids, "[{}]", FormatArrayAsHex(pr.grffile->grfid));
}
}
if (started > 0) {
@@ -2792,22 +2793,6 @@ static bool ConFramerateWindow(std::span<std::string_view> argv)
return true;
}
/**
* Format a label as a string.
* If all elements are visible ASCII (excluding space) then the label will be formatted as a string of 4 characters,
* otherwise it will be output as an 8-digit hexadecimal value.
* @param label Label to format.
* @return string representation of label.
**/
static std::string FormatLabel(uint32_t label)
{
if (std::isgraph(GB(label, 24, 8)) && std::isgraph(GB(label, 16, 8)) && std::isgraph(GB(label, 8, 8)) && std::isgraph(GB(label, 0, 8))) {
return fmt::format("{:c}{:c}{:c}{:c}", GB(label, 24, 8), GB(label, 16, 8), GB(label, 8, 8), GB(label, 0, 8));
}
return fmt::format("{:08X}", label);
}
/** List all road types and their configuration. */
static void ConDumpRoadTypes()
{
@@ -2818,31 +2803,31 @@ static void ConDumpRoadTypes()
IConsolePrint(CC_DEFAULT, " h = hidden");
IConsolePrint(CC_DEFAULT, " T = buildable by towns");
std::map<uint32_t, const GRFFile *> grfs;
std::map<GrfID, const GRFFile *> grfs;
for (RoadType rt : EnumRange(ROADTYPE_END)) {
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
if (rti->label == 0) continue;
uint32_t grfid = 0;
if (rti->label.Empty()) continue;
GrfID grfid{};
const GRFFile *grf = rti->grffile[RoadSpriteType::Ground];
if (grf != nullptr) {
grfid = grf->grfid;
grfs.emplace(grfid, grf);
}
IConsolePrint(CC_DEFAULT, " {:02d} {} {}, Flags: {}{}{}{}{}, GRF: {:08X}, {}",
IConsolePrint(CC_DEFAULT, " {:02d} {} {}, Flags: {}{}{}{}{}, GRF: {}, {}",
(uint)rt,
RoadTypeIsTram(rt) ? "Tram" : "Road",
FormatLabel(rti->label),
rti->label.AsString(),
rti->flags.Test(RoadTypeFlag::Catenary) ? 'c' : '-',
rti->flags.Test(RoadTypeFlag::NoLevelCrossing) ? 'l' : '-',
rti->flags.Test(RoadTypeFlag::NoHouses) ? 'X' : '-',
rti->flags.Test(RoadTypeFlag::Hidden) ? 'h' : '-',
rti->flags.Test(RoadTypeFlag::TownBuild) ? 'T' : '-',
std::byteswap(grfid),
FormatArrayAsHex(grfid),
GetStringPtr(rti->strings.name)
);
}
for (const auto &grf : grfs) {
IConsolePrint(CC_DEFAULT, " GRF: {:08X} = {}", std::byteswap(grf.first), grf.second->filename);
IConsolePrint(CC_DEFAULT, " GRF: {} = {}", FormatArrayAsHex(grf.first), grf.second->filename);
}
}
@@ -2857,31 +2842,31 @@ static void ConDumpRailTypes()
IConsolePrint(CC_DEFAULT, " a = always allow 90 degree turns");
IConsolePrint(CC_DEFAULT, " d = always disallow 90 degree turns");
std::map<uint32_t, const GRFFile *> grfs;
std::map<GrfID, const GRFFile *> grfs;
for (RailType rt : EnumRange(RAILTYPE_END)) {
const RailTypeInfo *rti = GetRailTypeInfo(rt);
if (rti->label == 0) continue;
uint32_t grfid = 0;
if (rti->label.Empty()) continue;
GrfID grfid{};
const GRFFile *grf = rti->grffile[RailSpriteType::Ground];
if (grf != nullptr) {
grfid = grf->grfid;
grfs.emplace(grfid, grf);
}
IConsolePrint(CC_DEFAULT, " {:02d} {}, Flags: {}{}{}{}{}{}, GRF: {:08X}, {}",
IConsolePrint(CC_DEFAULT, " {:02d} {}, Flags: {}{}{}{}{}{}, GRF: {}, {}",
(uint)rt,
FormatLabel(rti->label),
rti->label.AsString(),
rti->flags.Test(RailTypeFlag::Catenary) ? 'c' : '-',
rti->flags.Test(RailTypeFlag::NoLevelCrossing) ? 'l' : '-',
rti->flags.Test(RailTypeFlag::Hidden) ? 'h' : '-',
rti->flags.Test(RailTypeFlag::NoSpriteCombine) ? 's' : '-',
rti->flags.Test(RailTypeFlag::Allow90Deg) ? 'a' : '-',
rti->flags.Test(RailTypeFlag::Disallow90Deg) ? 'd' : '-',
std::byteswap(grfid),
FormatArrayAsHex(grfid),
GetStringPtr(rti->strings.name)
);
}
for (const auto &grf : grfs) {
IConsolePrint(CC_DEFAULT, " GRF: {:08X} = {}", std::byteswap(grf.first), grf.second->filename);
IConsolePrint(CC_DEFAULT, " GRF: {} = {}", FormatArrayAsHex(grf.first), grf.second->filename);
}
}
@@ -2906,18 +2891,18 @@ static void ConDumpCargoTypes()
IConsolePrint(CC_DEFAULT, " i = non-potable");
IConsolePrint(CC_DEFAULT, " S = special");
std::map<uint32_t, const GRFFile *> grfs;
std::map<GrfID, const GRFFile *> grfs;
for (const CargoSpec *spec : CargoSpec::Iterate()) {
uint32_t grfid = 0;
GrfID grfid{};
const GRFFile *grf = spec->grffile;
if (grf != nullptr) {
grfid = grf->grfid;
grfs.emplace(grfid, grf);
}
IConsolePrint(CC_DEFAULT, " {:02d} Bit: {:2d}, Label: {}, Callback mask: 0x{:02X}, Cargo class: {}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}, GRF: {:08X}, {}",
IConsolePrint(CC_DEFAULT, " {:02d} Bit: {:2d}, Label: {}, Callback mask: 0x{:02X}, Cargo class: {}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}, GRF: {}, {}",
spec->Index(),
spec->bitnum,
FormatLabel(spec->label.base()),
spec->label.AsString(),
spec->callback_mask.base(),
spec->classes.Test(CargoClass::Passengers) ? 'p' : '-',
spec->classes.Test(CargoClass::Mail) ? 'm' : '-',
@@ -2935,12 +2920,12 @@ static void ConDumpCargoTypes()
spec->classes.Test(CargoClass::Potable) ? 'e' : '-',
spec->classes.Test(CargoClass::NonPotable) ? 'i' : '-',
spec->classes.Test(CargoClass::Special) ? 'S' : '-',
std::byteswap(grfid),
FormatArrayAsHex(grfid),
GetStringPtr(spec->name)
);
}
for (const auto &grf : grfs) {
IConsolePrint(CC_DEFAULT, " GRF: {:08X} = {}", std::byteswap(grf.first), grf.second->filename);
IConsolePrint(CC_DEFAULT, " GRF: {} = {}", FormatArrayAsHex(grf.first), grf.second->filename);
}
}
+4 -4
View File
@@ -200,23 +200,23 @@ struct IConsoleWindow : Window
int ypos = this->height - this->line_height - WidgetDimensions::scaled.hsep_normal;
for (size_t line_index = IConsoleWindow::scroll; line_index < _iconsole_buffer.size(); line_index++) {
const IConsoleLine &print = _iconsole_buffer[line_index];
ypos = DrawStringMultiLine(WidgetDimensions::scaled.frametext.left, right, -this->line_height, ypos, GetString(STR_JUST_RAW_STRING, print.buffer), print.colour, SA_LEFT | SA_BOTTOM | SA_FORCE) - WidgetDimensions::scaled.hsep_normal;
ypos = DrawStringMultiLine(WidgetDimensions::scaled.frametext.left, right, -this->line_height, ypos, GetString(STR_JUST_RAW_STRING, print.buffer), print.colour, {AlignmentH::ForceLeft, AlignmentV::Bottom}) - WidgetDimensions::scaled.hsep_normal;
if (ypos < 0) break;
}
/* If the text is longer than the window, don't show the starting ']' */
int delta = this->width - WidgetDimensions::scaled.frametext.right - cursor_width - this->line_offset - _iconsole_cmdline.pixels - ICON_RIGHT_BORDERWIDTH;
if (delta > 0) {
DrawString(WidgetDimensions::scaled.frametext.left, right, this->height - this->line_height, "]", CC_COMMAND, SA_LEFT | SA_FORCE);
DrawString(WidgetDimensions::scaled.frametext.left, right, this->height - this->line_height, "]", CC_COMMAND, AlignmentH::ForceLeft);
delta = 0;
}
/* If we have a marked area, draw a background highlight. */
if (_iconsole_cmdline.marklength != 0) GfxFillRect(this->line_offset + delta + _iconsole_cmdline.markxoffs, this->height - this->line_height, this->line_offset + delta + _iconsole_cmdline.markxoffs + _iconsole_cmdline.marklength, this->height - 1, PC_DARK_RED);
DrawString(this->line_offset + delta, right, this->height - this->line_height, _iconsole_cmdline.GetText(), CC_COMMAND, SA_LEFT | SA_FORCE);
DrawString(this->line_offset + delta, right, this->height - this->line_height, _iconsole_cmdline.GetText(), CC_COMMAND, AlignmentH::ForceLeft);
if (_focused_window == this && _iconsole_cmdline.caret) {
DrawString(this->line_offset + delta + _iconsole_cmdline.caretxoffs, right, this->height - this->line_height, "_", TextColour::White, SA_LEFT | SA_FORCE);
DrawString(this->line_offset + delta + _iconsole_cmdline.caretxoffs, right, this->height - this->line_height, "_", TextColour::White, AlignmentH::ForceLeft);
}
}
+2
View File
@@ -13,6 +13,8 @@ add_files(
geometry_func.hpp
geometry_type.hpp
kdtree.hpp
label.cpp
label_type.hpp
math_func.cpp
math_func.hpp
multimap.hpp
+1 -1
View File
@@ -48,7 +48,7 @@ struct Backup {
if (this->valid) {
/* We cannot assert here, as missing restoration is 'normal' when exceptions are thrown.
* Exceptions are especially used to abort world generation. */
Debug(misc, 0, "{}:{}: Backed-up value was not restored!", this->location.file_name(), this->location.line());
Debug(Facility::Misc, Severity::Critical, "{}:{}: Backed-up value was not restored!", this->location.file_name(), this->location.line());
this->Restore();
}
}
+25 -23
View File
@@ -40,7 +40,7 @@ public:
* Set all bits.
* @returns The bit set
*/
inline constexpr Timpl &Set()
constexpr Timpl &Set()
{
this->data = Tmask;
return static_cast<Timpl&>(*this);
@@ -48,13 +48,15 @@ public:
/**
* Set the value-th bit.
* @tparam Treturn_type The returned type to which this bit set will be cast.
* @param value Bit to set.
* @returns The bit set
*/
inline constexpr Timpl &Set(Tvalue_type value)
template <typename Treturn_type = Timpl> requires std::is_base_of_v<BaseBitSet<Timpl, Tvalue_type, Tstorage, Tmask>, Treturn_type>
constexpr Treturn_type &Set(Tvalue_type value)
{
this->data |= (1ULL << Timpl::DecayValueType(value));
return static_cast<Timpl&>(*this);
return static_cast<Treturn_type &>(*this);
}
/**
@@ -62,7 +64,7 @@ public:
* @param other Bitset of values to set.
* @returns The bit set
*/
inline constexpr Timpl &Set(const Timpl &other)
constexpr Timpl &Set(const Timpl &other)
{
this->data |= other.data;
return static_cast<Timpl&>(*this);
@@ -74,7 +76,7 @@ public:
* @param set true if the bit should be set, false if the bit should be reset.
* @returns The EnumBitset
*/
inline constexpr Timpl &Set(Tvalue_type value, bool set)
constexpr Timpl &Set(Tvalue_type value, bool set)
{
return set ? this->Set(value) : this->Reset(value);
}
@@ -83,7 +85,7 @@ public:
* Reset all bits.
* @returns The bit set
*/
inline constexpr Timpl &Reset()
constexpr Timpl &Reset()
{
this->data = 0;
return static_cast<Timpl &>(*this);
@@ -94,7 +96,7 @@ public:
* @param value Bit to reset.
* @returns The bit set
*/
inline constexpr Timpl &Reset(Tvalue_type value)
constexpr Timpl &Reset(Tvalue_type value)
{
this->data &= ~(1ULL << Timpl::DecayValueType(value));
return static_cast<Timpl&>(*this);
@@ -105,7 +107,7 @@ public:
* @param other Bitset of values to reset.
* @returns The bit set
*/
inline constexpr Timpl &Reset(const Timpl &other)
constexpr Timpl &Reset(const Timpl &other)
{
this->data &= ~other.data;
return static_cast<Timpl&>(*this);
@@ -115,7 +117,7 @@ public:
* Flip all bits.
* @returns The bit set
*/
inline constexpr Timpl &Flip()
constexpr Timpl &Flip()
{
this->data ^= Tmask;
return static_cast<Timpl &>(*this);
@@ -126,7 +128,7 @@ public:
* @param value Bit to flip.
* @returns The bit set
*/
inline constexpr Timpl &Flip(Tvalue_type value)
constexpr Timpl &Flip(Tvalue_type value)
{
if (this->Test(value)) {
return this->Reset(value);
@@ -140,7 +142,7 @@ public:
* @param other Bitset of values to flip.
* @returns The bit set
*/
inline constexpr Timpl &Flip(const Timpl &other)
constexpr Timpl &Flip(const Timpl &other)
{
this->data ^= other.data;
return static_cast<Timpl&>(*this);
@@ -151,7 +153,7 @@ public:
* @param value Bit to check.
* @returns true iff the requested bit is set.
*/
inline constexpr bool Test(Tvalue_type value) const
constexpr bool Test(Tvalue_type value) const
{
return (this->data & (1ULL << Timpl::DecayValueType(value))) != 0;
}
@@ -161,7 +163,7 @@ public:
* @param other BitSet of values to test.
* @returns true iff all of the values are set.
*/
inline constexpr bool All(const Timpl &other) const
constexpr bool All(const Timpl &other) const
{
return (this->data & other.data) == other.data;
}
@@ -170,7 +172,7 @@ public:
* Test if all of the values are set.
* @returns true iff all of the values are set.
*/
inline constexpr bool All() const
constexpr bool All() const
{
return this->data == Tmask;
}
@@ -180,7 +182,7 @@ public:
* @param other BitSet of values to test.
* @returns true iff any of the given values are set.
*/
inline constexpr bool Any(const Timpl &other) const
constexpr bool Any(const Timpl &other) const
{
return (this->data & other.data) != 0;
}
@@ -189,7 +191,7 @@ public:
* Test if any of the values are set.
* @returns true iff any of the values are set.
*/
inline constexpr bool Any() const
constexpr bool Any() const
{
return this->data != 0;
}
@@ -198,29 +200,29 @@ public:
* Test if none of the values are set.
* @returns true iff none of the values are set.
*/
inline constexpr bool None() const
constexpr bool None() const
{
return this->data == 0;
}
inline constexpr Timpl &operator|=(const Timpl &other)
constexpr Timpl &operator|=(const Timpl &other)
{
this->data |= other.data;
return static_cast<Timpl &>(*this);
}
inline constexpr Timpl operator|(const Timpl &other) const
constexpr Timpl operator|(const Timpl &other) const
{
return Timpl{static_cast<Tstorage>(this->data | other.data)};
}
inline constexpr Timpl &operator&=(const Timpl &other)
constexpr Timpl &operator&=(const Timpl &other)
{
this->data &= other.data;
return static_cast<Timpl &>(*this);
}
inline constexpr Timpl operator&(const Timpl &other) const
constexpr Timpl operator&(const Timpl &other) const
{
return Timpl{static_cast<Tstorage>(this->data & other.data)};
}
@@ -229,7 +231,7 @@ public:
* Retrieve the raw value behind this bit set.
* @returns the raw value.
*/
inline constexpr Tstorage base() const noexcept
constexpr Tstorage base() const noexcept
{
return this->data;
}
@@ -238,7 +240,7 @@ public:
* Test that the raw value of this bit set is valid.
* @returns true iff the no bits outside the masked value are set.
*/
inline constexpr bool IsValid() const
constexpr bool IsValid() const
{
return (this->base() & Tmask) == this->base();
}
+2 -2
View File
@@ -29,7 +29,7 @@
* @return The selected bits, aligned to a LSB.
*/
template <typename T>
[[debug_inline]] inline constexpr static uint GB(const T x, const uint8_t s, const uint8_t n)
[[debug_inline]] static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
{
return (x >> s) & (((T)1U << n) - 1);
}
@@ -100,7 +100,7 @@ constexpr T AB(T &x, const uint8_t s, const uint8_t n, const U i)
* @return True if the bit is set, false else.
*/
template <typename T>
[[debug_inline]] inline constexpr bool HasBit(const T x, const uint8_t y)
[[debug_inline]] constexpr bool HasBit(const T x, const uint8_t y)
{
return (x & ((T)1U << y)) != 0;
}
+35 -20
View File
@@ -38,7 +38,7 @@ constexpr bool is_enum_incrementable_v = is_enum_incrementable<enum_type>::value
* @return Reference to the incremented enum.
*/
template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
inline constexpr enum_type &operator ++(enum_type &e)
constexpr enum_type &operator ++(enum_type &e)
{
e = static_cast<enum_type>(to_underlying(e) + 1);
return e;
@@ -50,7 +50,7 @@ inline constexpr enum_type &operator ++(enum_type &e)
* @return Copy of the original value.
*/
template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
inline constexpr enum_type operator ++(enum_type &e, int)
constexpr enum_type operator ++(enum_type &e, int)
{
enum_type e_org = e;
++e;
@@ -63,7 +63,7 @@ inline constexpr enum_type operator ++(enum_type &e, int)
* @return Reference to the decremented enum.
*/
template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
inline constexpr enum_type &operator --(enum_type &e)
constexpr enum_type &operator --(enum_type &e)
{
e = static_cast<enum_type>(to_underlying(e) - 1);
return e;
@@ -75,7 +75,7 @@ inline constexpr enum_type &operator --(enum_type &e)
* @return Copy of the original value.
*/
template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
inline constexpr enum_type operator --(enum_type &e, int)
constexpr enum_type operator --(enum_type &e, int)
{
enum_type e_org = e;
--e;
@@ -104,13 +104,13 @@ constexpr bool is_enum_sequential_v = is_enum_sequential<enum_type>::value;
* @return The new enum.
*/
template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
inline constexpr enum_type operator+(enum_type e, int offset)
constexpr enum_type operator+(enum_type e, int offset)
{
return static_cast<enum_type>(to_underlying(e) + offset);
}
template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
inline constexpr enum_type &operator+=(enum_type &e, int offset)
constexpr enum_type &operator+=(enum_type &e, int offset)
{
e = e + offset;
return e;
@@ -123,13 +123,13 @@ inline constexpr enum_type &operator+=(enum_type &e, int offset)
* @return The new enum.
*/
template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
inline constexpr enum_type operator-(enum_type e, int offset)
constexpr enum_type operator-(enum_type e, int offset)
{
return static_cast<enum_type>(to_underlying(e) - offset);
}
template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
inline constexpr enum_type &operator-=(enum_type &e, int offset)
constexpr enum_type &operator-=(enum_type &e, int offset)
{
e = e - offset;
return e;
@@ -142,7 +142,7 @@ inline constexpr enum_type &operator-=(enum_type &e, int offset)
* @return The value of the first enum minus the value of the second enum.
*/
template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
inline constexpr auto operator-(enum_type a, enum_type b)
constexpr auto operator-(enum_type a, enum_type b)
{
return to_underlying(a) - to_underlying(b);
}
@@ -155,13 +155,13 @@ inline constexpr auto operator-(enum_type a, enum_type b)
/** Operators to allow to work with enum as with type safe bit set in C++ */
#define DECLARE_ENUM_AS_BIT_SET(enum_type) \
inline constexpr enum_type operator | (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) | to_underlying(m2)); } \
inline constexpr enum_type operator & (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) & to_underlying(m2)); } \
inline constexpr enum_type operator ^ (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) ^ to_underlying(m2)); } \
inline constexpr enum_type& operator |= (enum_type& m1, enum_type m2) { m1 = m1 | m2; return m1; } \
inline constexpr enum_type& operator &= (enum_type& m1, enum_type m2) { m1 = m1 & m2; return m1; } \
inline constexpr enum_type& operator ^= (enum_type& m1, enum_type m2) { m1 = m1 ^ m2; return m1; } \
inline constexpr enum_type operator ~(enum_type m) { return static_cast<enum_type>(~to_underlying(m)); }
constexpr enum_type operator | (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) | to_underlying(m2)); } \
constexpr enum_type operator & (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) & to_underlying(m2)); } \
constexpr enum_type operator ^ (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) ^ to_underlying(m2)); } \
constexpr enum_type& operator |= (enum_type& m1, enum_type m2) { m1 = m1 | m2; return m1; } \
constexpr enum_type& operator &= (enum_type& m1, enum_type m2) { m1 = m1 & m2; return m1; } \
constexpr enum_type& operator ^= (enum_type& m1, enum_type m2) { m1 = m1 ^ m2; return m1; } \
constexpr enum_type operator ~(enum_type m) { return static_cast<enum_type>(~to_underlying(m)); }
/** Operator that allows this enumeration to be added to any other enumeration. */
#define DECLARE_ENUM_AS_ADDABLE(EnumType) \
@@ -181,7 +181,7 @@ inline constexpr auto operator-(enum_type a, enum_type b)
* @return True iff the flag is set.
*/
template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
[[debug_inline]] inline constexpr bool HasFlag(const T x, const T y)
[[debug_inline]] constexpr bool HasFlag(const T x, const T y)
{
return (x & y) == y;
}
@@ -192,7 +192,7 @@ template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
* @param y The flag to toggle.
*/
template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
[[debug_inline]] inline constexpr void ToggleFlag(T &x, const T y)
[[debug_inline]] constexpr void ToggleFlag(T &x, const T y)
{
if (HasFlag(x, y)) {
x &= ~y;
@@ -304,7 +304,19 @@ public:
using EnumType = BaseClass::ValueType;
constexpr EnumBitSet() : BaseClass() {}
constexpr EnumBitSet(Tenum value) : BaseClass() { this->Set(value); }
/**
* Construct an EnumBitSet from an enum value.
* @param value The single enum value to be set.
*/
constexpr EnumBitSet(Tenum value) : BaseClass()
{
/* MSVC 19.44 and older does not consider cast of dynamic type (e.g. BaseBitSet) to EnumBitSet as constant,
* when the EnumBitSet is constructed inside an initializer list like we do for many lookup tables.
* By setting the return type to BaseClass the cast becomes redundant and compilation does not fail. */
this->template Set<BaseClass>(value);
}
explicit constexpr EnumBitSet(Tstorage data) : BaseClass(data) {}
/**
@@ -314,7 +326,10 @@ public:
constexpr EnumBitSet(std::initializer_list<const Tenum> values) : BaseClass()
{
for (const Tenum &value : values) {
this->Set(value);
/* MSVC 19.44 and older does not consider cast of dynamic type (e.g. BaseBitSet) to EnumBitSet as constant,
* when the EnumBitSet is constructed inside an initializer list like we do for many lookup tables.
* By setting the return type to BaseClass the cast becomes redundant and compilation does not fail. */
this->template Set<BaseClass>(value);
}
}
+15
View File
@@ -10,9 +10,24 @@
#include "../stdafx.h"
#include "geometry_func.hpp"
#include "math_func.hpp"
#include "../strings_func.h"
#include "../strings_type.h"
#include "../safeguards.h"
/**
* Resolve horizontal alignment for the current text direction.
* @return The resolved horizontal alignment.
*/
AlignmentH Alignment::ResolveRTL() const
{
switch (this->h) {
case AlignmentH::Start: return _current_text_dir == TD_RTL ? AlignmentH::ForceRight : AlignmentH::ForceLeft;
case AlignmentH::End: return _current_text_dir == TD_RTL ? AlignmentH::ForceLeft : AlignmentH::ForceRight;
default: return this->h;
}
}
/**
* Compute bounding box of both dimensions.
* @param d1 First dimension.
+49 -4
View File
@@ -16,6 +16,43 @@
# define Point OTTD_Point
#endif /* __APPLE__ */
/** Horizontal alignments. */
enum class AlignmentH : uint8_t {
Start, ///< Align to the start, LTR/RTL aware.
Centre, ///< Align to the centre.
End, ///< Align to the end, LTR/RTL aware.
ForceLeft, ///< Force align to the left.
ForceRight, ///< Force align to the right.
};
/** Vertical alignments. */
enum class AlignmentV : uint8_t {
Top, ///< Align to the top.
Middle, ///< Align to the middle.
Bottom, ///< Align to the bottom.
};
/** Horizontal and vertical alignment. */
struct Alignment {
AlignmentH h; ///< Horizontal alignment.
AlignmentV v; ///< Vertical alignment.
/**
* Construct an alignment with the specified horizontal and vertical alignment.
* @param h The horizontal alignment.
* @param v The vertical alignment.
*/
constexpr Alignment(AlignmentH h, AlignmentV v) : h(h), v(v) {}
/**
* Construct an alignment with the specific horizontal alignment.
* @param h The horizontal alignment.
*/
constexpr Alignment(AlignmentH h) : Alignment(h, AlignmentV::Top) {}
AlignmentH ResolveRTL() const;
};
/**
* Determine where to position a centred object.
* @param min The top or left coordinate.
@@ -66,11 +103,19 @@ using Point = Coord2D<int>;
/** Dimensions (a width and height) of a rectangle in 2D */
struct Dimension {
uint width;
uint height;
using value_type = uint32_t; ///< The type of the values; hack to make this look enough like a std::array for saving/loading resolutions
value_type width = 0; ///< The width of the rectangle.
value_type height = 0; ///< The height of the rectangle.
constexpr Dimension() : width(0), height(0) {}
constexpr Dimension(uint w, uint h) : width(w), height(h) {}
/** Create a 0x0 dimension. */
constexpr Dimension() = default;
/**
* Create a dimension.
* @param w The width.
* @param h The height.
*/
constexpr Dimension(value_type w, value_type h) : width(w), height(h) {}
bool operator< (const Dimension &other) const
{
+29
View File
@@ -0,0 +1,29 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
*/
/** @file label.cpp Implementation of label functions. */
#include "../stdafx.h"
#include "label_type.hpp"
#include "../string_func.h"
#include "../safeguards.h"
/**
* Get the label as a \c std::string.
* If the label is all \c std::isgraph characters, it will return these characters as string,
* otherwise it will format it as a 8-digit hexadecimal.
* @return The label as string.
*/
std::string BaseLabel::AsString() const
{
if (std::ranges::all_of(*this, [](uint8_t c) { return std::isgraph(c); })) {
return std::string{reinterpret_cast<const char *>(this->data()), this->size()};
}
return FormatArrayAsHex(*this);
}
+72
View File
@@ -0,0 +1,72 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
*/
/** @file label_type.hpp A type for 4 character labels/tags/ids in files that should be read/shown as is. */
#ifndef LABEL_TYPE_HPP
#define LABEL_TYPE_HPP
/** Base for a four character label/tag/id. */
struct BaseLabel : std::array<uint8_t, 4> {
/**
* Check whether the label is empty.
* @return \c true iff the label is empty, i.e. all zeros.
*/
constexpr bool Empty() const
{
return std::ranges::all_of(*this, [](uint8_t b) { return b == 0; });
};
/**
* Get the label as a \c std::string.
* If the label is all \c std::isgraph characters, it will return these characters as string,
* otherwise it will format it as a 8-digit hexadecimal.
* @return The label as string.
*/
std::string AsString() const;
};
/**
* A four character label/tag/id.
* @tparam Tag Type to distinguish labels/tags/ids of different types.
*/
template <typename Tag>
struct Label : BaseLabel {
/** Create an empty label, i.e. all zeros. */
constexpr Label()
{
std::ranges::fill(*this, 0);
}
/**
* Create a label with the given 4 letter character string.
* @param label The label value.
* @note This defines 5 characters, but the 5th character is assumed to null-terminator.
*/
constexpr Label(const char (&label)[5])
{
std::copy(label, label + this->size(), this->begin());
}
/**
* Create a label with the given 4 bytes.
* @param label The label value.
*/
constexpr Label(const uint8_t (&label)[4])
{
std::copy(label, label + this->size(), this->begin());
}
/**
* Default spaceship operator.
* @param other The label to compare to.
* @return The comparison ordering.
*/
constexpr std::strong_ordering operator<=>(const Label<Tag> &other) const = default;
};
#endif /* LABEL_TYPE_HPP */
+8
View File
@@ -252,6 +252,10 @@ constexpr bool IsInsideBS(const T x, const size_t base, const size_t size)
return static_cast<size_t>(x - base) < size;
}
/** Specialization of IsInsideBS for #ConvertibleThroughBase. @copydoc IsInsideBS(const T, const size_t, const size_t) */
template <ConvertibleThroughBase T>
constexpr bool IsInsideBS(const T x, const T base, const size_t size) noexcept { return IsInsideBS(x.base(), base.base(), size); }
/**
* Checks if a value is in an interval.
*
@@ -271,6 +275,10 @@ constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) no
/** Specialization of IsInsideMM for #ConvertibleThroughBase. @copydoc IsInsideMM(const size_t, const size_t, const size_t) */
constexpr bool IsInsideMM(const ConvertibleThroughBase auto x, const size_t min, const size_t max) noexcept { return IsInsideMM(x.base(), min, max); }
/** Specialization of IsInsideMM for #ConvertibleThroughBase. @copydoc IsInsideMM(const size_t, const size_t, const size_t) */
template <ConvertibleThroughBase T>
constexpr bool IsInsideMM(const T x, const T min, const T max) noexcept { return IsInsideMM(x.base(), min.base(), max.base()); }
/** Specialization of IsInsideMM for enums. @copydoc IsInsideMM(const size_t, const size_t, const size_t) */
template <typename enum_type, std::enable_if_t<std::is_enum_v<enum_type>, bool> = true>
constexpr bool IsInsideMM(enum_type x, enum_type min, enum_type max) noexcept
+54 -54
View File
@@ -42,10 +42,10 @@ public:
constexpr OverflowSafeInt(const OverflowSafeInt &other) : m_value(other.m_value) { }
constexpr OverflowSafeInt(const T int_) : m_value(int_) { }
inline constexpr OverflowSafeInt& operator = (const OverflowSafeInt& other) { this->m_value = other.m_value; return *this; }
inline constexpr OverflowSafeInt& operator = (T other) { this->m_value = other; return *this; }
constexpr OverflowSafeInt& operator = (const OverflowSafeInt& other) { this->m_value = other.m_value; return *this; }
constexpr OverflowSafeInt& operator = (T other) { this->m_value = other; return *this; }
inline constexpr OverflowSafeInt operator - () const { return OverflowSafeInt(this->m_value == T_MIN ? T_MAX : -this->m_value); }
constexpr OverflowSafeInt operator - () const { return OverflowSafeInt(this->m_value == T_MIN ? T_MAX : -this->m_value); }
/**
* Safe implementation of addition.
@@ -53,7 +53,7 @@ public:
* @return Reference to this instance.
* @note when the addition would yield more than T_MAX, it will be T_MAX.
*/
inline constexpr OverflowSafeInt& operator += (const OverflowSafeInt& other)
constexpr OverflowSafeInt& operator += (const OverflowSafeInt& other)
{
#ifdef HAS_OVERFLOW_BUILTINS
if (__builtin_add_overflow(this->m_value, other.m_value, &this->m_value)) [[unlikely]] {
@@ -77,7 +77,7 @@ public:
* @return Reference to this instance.
* @note when the subtraction would yield less than T_MIN, it will be T_MIN.
*/
inline constexpr OverflowSafeInt& operator -= (const OverflowSafeInt& other)
constexpr OverflowSafeInt& operator -= (const OverflowSafeInt& other)
{
#ifdef HAS_OVERFLOW_BUILTINS
if (__builtin_sub_overflow(this->m_value, other.m_value, &this->m_value)) [[unlikely]] {
@@ -96,17 +96,17 @@ public:
}
/* Operators for addition and subtraction. */
inline constexpr OverflowSafeInt operator + (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result += other; return result; }
inline constexpr OverflowSafeInt operator + (const int other) const { OverflowSafeInt result = *this; result += (int64_t)other; return result; }
inline constexpr OverflowSafeInt operator + (const uint other) const { OverflowSafeInt result = *this; result += (int64_t)other; return result; }
inline constexpr OverflowSafeInt operator - (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result -= other; return result; }
inline constexpr OverflowSafeInt operator - (const int other) const { OverflowSafeInt result = *this; result -= (int64_t)other; return result; }
inline constexpr OverflowSafeInt operator - (const uint other) const { OverflowSafeInt result = *this; result -= (int64_t)other; return result; }
constexpr OverflowSafeInt operator + (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result += other; return result; }
constexpr OverflowSafeInt operator + (const int other) const { OverflowSafeInt result = *this; result += (int64_t)other; return result; }
constexpr OverflowSafeInt operator + (const uint other) const { OverflowSafeInt result = *this; result += (int64_t)other; return result; }
constexpr OverflowSafeInt operator - (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result -= other; return result; }
constexpr OverflowSafeInt operator - (const int other) const { OverflowSafeInt result = *this; result -= (int64_t)other; return result; }
constexpr OverflowSafeInt operator - (const uint other) const { OverflowSafeInt result = *this; result -= (int64_t)other; return result; }
inline constexpr OverflowSafeInt& operator ++ () { return *this += 1; }
inline constexpr OverflowSafeInt& operator -- () { return *this += -1; }
inline constexpr OverflowSafeInt operator ++ (int) { OverflowSafeInt org = *this; *this += 1; return org; }
inline constexpr OverflowSafeInt operator -- (int) { OverflowSafeInt org = *this; *this += -1; return org; }
constexpr OverflowSafeInt& operator ++ () { return *this += 1; }
constexpr OverflowSafeInt& operator -- () { return *this += -1; }
constexpr OverflowSafeInt operator ++ (int) { OverflowSafeInt org = *this; *this += 1; return org; }
constexpr OverflowSafeInt operator -- (int) { OverflowSafeInt org = *this; *this += -1; return org; }
/**
* Safe implementation of multiplication.
@@ -115,7 +115,7 @@ public:
* @note when the multiplication would yield more than T_MAX (or less than T_MIN),
* it will be T_MAX (respectively T_MIN).
*/
inline constexpr OverflowSafeInt& operator *= (const int factor)
constexpr OverflowSafeInt& operator *= (const int factor)
{
#ifdef HAS_OVERFLOW_BUILTINS
const bool is_result_positive = (this->m_value < 0) == (factor < 0); // -ve * -ve == +ve
@@ -141,68 +141,68 @@ public:
}
/* Operators for multiplication. */
inline constexpr OverflowSafeInt operator * (const int64_t factor) const { OverflowSafeInt result = *this; result *= factor; return result; }
inline constexpr OverflowSafeInt operator * (const int factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; }
inline constexpr OverflowSafeInt operator * (const uint factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; }
inline constexpr OverflowSafeInt operator * (const uint16_t factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; }
inline constexpr OverflowSafeInt operator * (const uint8_t factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; }
constexpr OverflowSafeInt operator * (const int64_t factor) const { OverflowSafeInt result = *this; result *= factor; return result; }
constexpr OverflowSafeInt operator * (const int factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; }
constexpr OverflowSafeInt operator * (const uint factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; }
constexpr OverflowSafeInt operator * (const uint16_t factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; }
constexpr OverflowSafeInt operator * (const uint8_t factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; }
/* Operators for division. */
inline constexpr OverflowSafeInt& operator /= (const int64_t divisor) { this->m_value /= divisor; return *this; }
inline constexpr OverflowSafeInt operator / (const OverflowSafeInt& divisor) const { OverflowSafeInt result = *this; result /= divisor.m_value; return result; }
inline constexpr OverflowSafeInt operator / (const int divisor) const { OverflowSafeInt result = *this; result /= divisor; return result; }
inline constexpr OverflowSafeInt operator / (const uint divisor) const { OverflowSafeInt result = *this; result /= (int)divisor; return result; }
constexpr OverflowSafeInt& operator /= (const int64_t divisor) { this->m_value /= divisor; return *this; }
constexpr OverflowSafeInt operator / (const OverflowSafeInt& divisor) const { OverflowSafeInt result = *this; result /= divisor.m_value; return result; }
constexpr OverflowSafeInt operator / (const int divisor) const { OverflowSafeInt result = *this; result /= divisor; return result; }
constexpr OverflowSafeInt operator / (const uint divisor) const { OverflowSafeInt result = *this; result /= (int)divisor; return result; }
/* Operators for modulo */
inline constexpr OverflowSafeInt& operator %= (const int divisor) { this->m_value %= divisor; return *this; }
inline constexpr OverflowSafeInt operator % (const int divisor) const { OverflowSafeInt result = *this; result %= divisor; return result; }
constexpr OverflowSafeInt& operator %= (const int divisor) { this->m_value %= divisor; return *this; }
constexpr OverflowSafeInt operator % (const int divisor) const { OverflowSafeInt result = *this; result %= divisor; return result; }
/* Operators for shifting. */
inline constexpr OverflowSafeInt& operator <<= (const int shift) { this->m_value <<= shift; return *this; }
inline constexpr OverflowSafeInt operator << (const int shift) const { OverflowSafeInt result = *this; result <<= shift; return result; }
inline constexpr OverflowSafeInt& operator >>= (const int shift) { this->m_value >>= shift; return *this; }
inline constexpr OverflowSafeInt operator >> (const int shift) const { OverflowSafeInt result = *this; result >>= shift; return result; }
constexpr OverflowSafeInt& operator <<= (const int shift) { this->m_value <<= shift; return *this; }
constexpr OverflowSafeInt operator << (const int shift) const { OverflowSafeInt result = *this; result <<= shift; return result; }
constexpr OverflowSafeInt& operator >>= (const int shift) { this->m_value >>= shift; return *this; }
constexpr OverflowSafeInt operator >> (const int shift) const { OverflowSafeInt result = *this; result >>= shift; return result; }
/* Operators for (in)equality when comparing overflow safe ints. */
inline constexpr bool operator == (const OverflowSafeInt& other) const { return this->m_value == other.m_value; }
inline constexpr auto operator <=>(const OverflowSafeInt& other) const { return this->m_value <=> other.m_value; }
constexpr bool operator == (const OverflowSafeInt& other) const { return this->m_value == other.m_value; }
constexpr auto operator <=>(const OverflowSafeInt& other) const { return this->m_value <=> other.m_value; }
/* Operators for (in)equality when comparing non-overflow safe ints. */
inline constexpr bool operator == (const int other) const { return this->m_value == other; }
inline constexpr auto operator <=>(const int other) const { return this->m_value <=> other; }
constexpr bool operator == (const int other) const { return this->m_value == other; }
constexpr auto operator <=>(const int other) const { return this->m_value <=> other; }
inline constexpr operator T () const { return this->m_value; }
constexpr operator T () const { return this->m_value; }
static inline constexpr OverflowSafeInt<T> max() { return T_MAX; }
static inline constexpr OverflowSafeInt<T> min() { return T_MIN; }
static constexpr OverflowSafeInt<T> max() { return T_MAX; }
static constexpr OverflowSafeInt<T> min() { return T_MIN; }
BaseType base() const noexcept { return this->m_value; }
};
/* Sometimes we got int64_t operator OverflowSafeInt instead of vice versa. Handle that properly. */
template <class T> inline constexpr OverflowSafeInt<T> operator + (const int64_t a, const OverflowSafeInt<T> b) { return b + a; }
template <class T> inline constexpr OverflowSafeInt<T> operator - (const int64_t a, const OverflowSafeInt<T> b) { return -b + a; }
template <class T> inline constexpr OverflowSafeInt<T> operator * (const int64_t a, const OverflowSafeInt<T> b) { return b * a; }
template <class T> inline constexpr OverflowSafeInt<T> operator / (const int64_t a, const OverflowSafeInt<T> b) { return (OverflowSafeInt<T>)a / (int)b; }
template <class T> constexpr OverflowSafeInt<T> operator + (const int64_t a, const OverflowSafeInt<T> b) { return b + a; }
template <class T> constexpr OverflowSafeInt<T> operator - (const int64_t a, const OverflowSafeInt<T> b) { return -b + a; }
template <class T> constexpr OverflowSafeInt<T> operator * (const int64_t a, const OverflowSafeInt<T> b) { return b * a; }
template <class T> constexpr OverflowSafeInt<T> operator / (const int64_t a, const OverflowSafeInt<T> b) { return (OverflowSafeInt<T>)a / (int)b; }
/* Sometimes we got int operator OverflowSafeInt instead of vice versa. Handle that properly. */
template <class T> inline constexpr OverflowSafeInt<T> operator + (const int a, const OverflowSafeInt<T> b) { return b + a; }
template <class T> inline constexpr OverflowSafeInt<T> operator - (const int a, const OverflowSafeInt<T> b) { return -b + a; }
template <class T> inline constexpr OverflowSafeInt<T> operator * (const int a, const OverflowSafeInt<T> b) { return b * a; }
template <class T> inline constexpr OverflowSafeInt<T> operator / (const int a, const OverflowSafeInt<T> b) { return (OverflowSafeInt<T>)a / (int)b; }
template <class T> constexpr OverflowSafeInt<T> operator + (const int a, const OverflowSafeInt<T> b) { return b + a; }
template <class T> constexpr OverflowSafeInt<T> operator - (const int a, const OverflowSafeInt<T> b) { return -b + a; }
template <class T> constexpr OverflowSafeInt<T> operator * (const int a, const OverflowSafeInt<T> b) { return b * a; }
template <class T> constexpr OverflowSafeInt<T> operator / (const int a, const OverflowSafeInt<T> b) { return (OverflowSafeInt<T>)a / (int)b; }
/* Sometimes we got uint operator OverflowSafeInt instead of vice versa. Handle that properly. */
template <class T> inline constexpr OverflowSafeInt<T> operator + (const uint a, const OverflowSafeInt<T> b) { return b + a; }
template <class T> inline constexpr OverflowSafeInt<T> operator - (const uint a, const OverflowSafeInt<T> b) { return -b + a; }
template <class T> inline constexpr OverflowSafeInt<T> operator * (const uint a, const OverflowSafeInt<T> b) { return b * a; }
template <class T> inline constexpr OverflowSafeInt<T> operator / (const uint a, const OverflowSafeInt<T> b) { return (OverflowSafeInt<T>)a / (int)b; }
template <class T> constexpr OverflowSafeInt<T> operator + (const uint a, const OverflowSafeInt<T> b) { return b + a; }
template <class T> constexpr OverflowSafeInt<T> operator - (const uint a, const OverflowSafeInt<T> b) { return -b + a; }
template <class T> constexpr OverflowSafeInt<T> operator * (const uint a, const OverflowSafeInt<T> b) { return b * a; }
template <class T> constexpr OverflowSafeInt<T> operator / (const uint a, const OverflowSafeInt<T> b) { return (OverflowSafeInt<T>)a / (int)b; }
/* Sometimes we got byte operator OverflowSafeInt instead of vice versa. Handle that properly. */
template <class T> inline constexpr OverflowSafeInt<T> operator + (const uint8_t a, const OverflowSafeInt<T> b) { return b + (uint)a; }
template <class T> inline constexpr OverflowSafeInt<T> operator - (const uint8_t a, const OverflowSafeInt<T> b) { return -b + (uint)a; }
template <class T> inline constexpr OverflowSafeInt<T> operator * (const uint8_t a, const OverflowSafeInt<T> b) { return b * (uint)a; }
template <class T> inline constexpr OverflowSafeInt<T> operator / (const uint8_t a, const OverflowSafeInt<T> b) { return (OverflowSafeInt<T>)a / (int)b; }
template <class T> constexpr OverflowSafeInt<T> operator + (const uint8_t a, const OverflowSafeInt<T> b) { return b + (uint)a; }
template <class T> constexpr OverflowSafeInt<T> operator - (const uint8_t a, const OverflowSafeInt<T> b) { return -b + (uint)a; }
template <class T> constexpr OverflowSafeInt<T> operator * (const uint8_t a, const OverflowSafeInt<T> b) { return b * (uint)a; }
template <class T> constexpr OverflowSafeInt<T> operator / (const uint8_t a, const OverflowSafeInt<T> b) { return (OverflowSafeInt<T>)a / (int)b; }
typedef OverflowSafeInt<int64_t> OverflowSafeInt64;
typedef OverflowSafeInt<int32_t> OverflowSafeInt32;
+4 -4
View File
@@ -72,7 +72,7 @@ void SetRandomSeed(uint32_t seed)
uint32_t Random(const std::source_location location)
{
if (_networking && (!_network_server || (NetworkClientSocket::IsValidID(0) && NetworkClientSocket::Get(0)->status != NetworkClientSocket::ClientStatus::Inactive))) {
Debug(random, 0, "{:08x}; {:02x}; {:04x}; {:02x}; {}:{}", TimerGameEconomy::date, TimerGameEconomy::date_fract, _frame_counter, _current_company, location.file_name(), location.line());
Debug(Facility::Random, Severity::Critical, "{:08x}; {:02x}; {:04x}; {:02x}; {}:{}", TimerGameEconomy::date, TimerGameEconomy::date_fract, _frame_counter, _current_company, location.file_name(), location.line());
}
return _random.Next();
@@ -120,9 +120,9 @@ void RandomBytesWithFallback(std::span<uint8_t> buf)
# warning "No cryptographically-strong random generator available; using a fallback instead"
#endif
static bool warned_once = false;
Debug(misc, warned_once ? 1 : 0, "Cryptographically-strong random generator unavailable; using fallback");
warned_once = true;
static Severity severity = Severity::Critical;
Debug(Facility::Misc, severity, "Cryptographically-strong random generator unavailable; using fallback");
severity = Severity::Error;
for (uint i = 0; i < buf.size(); i++) {
buf[i] = static_cast<uint8_t>(InteractiveRandom());
+7
View File
@@ -91,6 +91,13 @@ inline uint32_t RandomRange(uint32_t limit, const std::source_location location
return ScaleToLimit(Random(location), limit);
}
/** @copydoc RandomRange */
template <typename T> requires std::is_enum_v<T>
inline T RandomRange(T limit, const std::source_location location = std::source_location::current())
{
return static_cast<T>(RandomRange(to_underlying(limit), location));
}
inline uint32_t InteractiveRandom()
{
return _interactive_random.Next();
+1 -1
View File
@@ -35,7 +35,7 @@
#if defined(STRGEN) || defined(SETTINGSGEN)
FatalErrorI(std::move(msg));
#else
DebugPrint("misc", 0, std::move(msg));
DebugPrint(Facility::Misc, Severity::Critical, std::move(msg));
#endif
}
+1 -1
View File
@@ -9,6 +9,7 @@
#include "stdafx.h"
#include "core/bitmath_func.hpp"
#include "cpu.h"
#include "safeguards.h"
@@ -72,7 +73,6 @@ static CPUIDArray CPUID([[maybe_unused]] int type)
info[3] |= (1<<26); /* HasCPUIDFlag(1, 3, 26) */
# endif
}
}
#endif
return info;
}
+1 -1
View File
@@ -15,7 +15,7 @@
#include "music/music_driver.hpp"
#include "sound/sound_driver.hpp"
#include "video/video_driver.hpp"
#include "saveload/saveload.h"
#include "saveload/saveload_func.h"
#include "screenshot.h"
#include "network/network_survey.h"
#include "news_func.h"

Some files were not shown because too many files have changed in this diff Show More