Old combined cargo/industry sets may set up cargo types with labels and expect them to be usable without a translation table.
Install a fallback table if the NewGRF does not install one to give them a better chance of working.
If the small font is set larger than the normal font, both name and version text disappeared.
Take account of the height of the small font when setting the resize height.
Fix script list sorter to correctly retarget iterator when swapping lists.
Each sorter implementation now updates its internal iterator to remain valid after attaching to a new list, avoiding undefined behaviour.
Add convenience helpers to correctly retrieve goods entry cargo available/totals.
Avoids having to check if cargo data is available before accessing it, which was missing for autorefit.
Order Load and Unload flags have complex logic to ensure that invalid combinations aren't used. In fact, apart from FullLoad and FullLoadAny, all mixed combinations are invalid.
Simplify logic by removing the use of bit values and treat each option as a value.
The NewGRF spec does not mention that sprite group `type` and the `num-ent1` fields are the same.
Reserve all unrecognised special types in case they are wanted at some point.
english (au): 9 changes by krysclarke
swedish: 17 changes by robert-i
english (us): 17 changes by 2TallTyler
greek: 9 changes by gh658804
russian: 9 changes by Ln-Wolf
finnish: 9 changes by hpiirai
portuguese (brazilian): 9 changes by pasantoro
polish: 9 changes by pAter-exe
english (au): 8 changes by krysclarke
greek: 8 changes by gh658804
russian: 8 changes by Ln-Wolf
finnish: 8 changes by hpiirai
portuguese: 8 changes by jcteotonio
portuguese (brazilian): 8 changes by pasantoro
polish: 10 changes by pAter-exe
ProcessRegisters must be called even if the sprite resolve result
is not valid.
A zero-length ResultSpriteGroup is valid because the output value
is an offset, not a sprite ID within the ResultSpriteGroup.
Replaces the fixed-size array for company sorting with a std::vector and updates sorting to use std::ranges::sort. This removes the need for manual count management.
The logic in ConNetworkAuthorizedKey for the `authorized_key` command was inverted.
The check `if (StrEqualsIgnoreCase(type, name)) continue;` caused the action (add/remove) to be incorrectly executed on the first key type encountered that *did not* match the requested type, rather than the intended one. This resulted in keys specified for 'admin' being added to 'rcon', for example.
This commit inverts the condition to ensure the action is performed only when the requested type matches the iterated key name.
english (au): 4 changes by krysclarke
english (us): 4 changes by 2TallTyler
greek: 4 changes by gh658804
hungarian: 4 changes by vargaviktor
russian: 4 changes by Ln-Wolf
finnish: 4 changes by hpiirai
portuguese: 4 changes by jcteotonio
portuguese (brazilian): 4 changes by pasantoro
english (au): 11 changes by krysclarke
swedish: 11 changes by robert-i
chinese (traditional): 11 changes by KogentaSan
greek: 11 changes by gh658804
russian: 13 changes by Ln-Wolf
finnish: 15 changes by hpiirai
portuguese: 44 changes by jcteotonio
portuguese (brazilian): 11 changes by pasantoro, 1 change by jcteotonio
polish: 10 changes by Rito13, 1 change by pAter-exe
swedish: 1 change by robert-i
norwegian (bokmal): 4 changes by eriksorngard
chinese (simplified): 4 changes by WenSimEHRP
catalan: 1 change by J0anJosep
danish: 4 changes by bscargo
latvian: 8 changes by lexuslatvia
dutch: 4 changes by Afoklala
french: 5 changes by ottdfevr
* Use `iter->` instead of `(*iter).`
* Use prefix instead of postfix operators
* Use `auto` instead of explicit iterator type.
* Use `std::next()` instead of assignment then increment.
* Use range-for where possible.
english (au): 1 change by krysclarke
greek: 1 change by gh658804
hungarian: 4 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
Instead of calculating and storing which buttons to display for each
line and then further calculating what each line should be when
displaying it, store everything on one pass.
This simplifies/deduplicates logic.
english (au): 3 changes by krysclarke
swedish: 3 changes by robert-i
korean: 3 changes by telk5093
greek: 3 changes by gh658804
russian: 3 changes by Ln-Wolf
finnish: 3 changes by hpiirai
catalan: 3 changes by J0anJosep
portuguese: 3 changes by jcteotonio
portuguese (brazilian): 3 changes by pasantoro
polish: 3 changes by pAter-exe
When building a custom station, the callback-derived tile layout is ignored during the bridge height test. This caused a discrepancy between building a station under a bridge vs building a bridge over the same station.
Test the station tile layout callback during the bridge height test.
`HandleScrollbarHittest` returns min and max coordinates, not x and y.
Also avoid referring to the min and max coordinates as top and bottom, as these functions are used for both vertical and horizontal scrollbars.
_setting_circle_size and (the incorrectly named) SETTING_HEIGHT variables are now static members of BaseSettingEntry.
Neither of these are constants, so they no longer use constant naming style.
* ShowDropDownList() now issues a beep, so individual toolbar buttons no longer need to do it.
* HandleButtonClick() may be called twice for some buttons, as it is called by automatically for PUSH buttons.
This caused some beeps to sound louder than others.
Replace OS-dependent interface scaling with scaling dependent on the window size.
This works on all platforms and should provide a more comfortable experience for new players. Manual interface scale setting works as before.
swedish: 2 changes by robert-i
norwegian (bokmal): 4 changes by eriksorngard
chinese (traditional): 5 changes by KogentaSan
english (us): 5 changes by 2TallTyler
greek: 2 changes by gh658804
russian: 2 changes by Ln-Wolf
finnish: 2 changes by hpiirai
danish: 2 changes by bscargo
portuguese: 6 changes by jcteotonio
portuguese (brazilian): 9 changes by pasantoro
polish: 12 changes by pAter-exe
english (au): 1 change by krysclarke
swedish: 1 change by robert-i
chinese (traditional): 1 change by KogentaSan
chinese (simplified): 2 changes by WenSimEHRP
korean: 1 change by telk5093
greek: 1 change by gh658804
finnish: 1 change by hpiirai
portuguese: 9 changes by jcteotonio
portuguese (brazilian): 1 change by pasantoro
polish: 1 change by Rito13
* Compare against the size of the array instead of the constant used to define the array.
* `type_map` alias now uses auto to avoid defining the type each time.
* `_cur_gps.grffile->railtype_map` is now aliased to `type_map` to simplify and standardise.
english (us): 1 change by 2TallTyler
korean: 1 change by telk5093
hungarian: 1 change by vargaviktor
danish: 2 changes by New-Authentication
dutch: 1 change by nicobresseleers
portuguese: 12 changes by jcteotonio
english (au): 1 change by krysclarke
swedish: 1 change by robert-i
chinese (traditional): 1 change by KogentaSan
vietnamese: 1 change by KhoiCanDev
greek: 1 change by gh658804
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
portuguese: 76 changes by jcteotonio
portuguese (brazilian): 1 change by pasantoro
polish: 4 changes by pAter-exe
Add new private range special symbols for recent OpenTTD updates: town and city icons for sans (supporting #14504), left arrow for small and sans (supporting #14174). Add Hebrew alphabet to small and serif fonts, for first (beta) support for Hebrew. Fix new shekel glyph height in all fonts. Fix i ogonek right bearing and umlaut alignment in sans font. Fixes#14179
The table in landscape_grid.html uses both the letter `O` as well as the digit `0` (zero) to denote bits.
The digit `0` represents actual values, while the letter `O` is a placeholder for free bits.
english (au): 5 changes by krysclarke
chinese (traditional): 5 changes by KogentaSan
russian: 5 changes by Ln-Wolf
finnish: 8 changes by hpiirai
portuguese: 7 changes by jcteotonio
portuguese (brazilian): 6 changes by pasantoro
polish: 5 changes by pAter-exe
swedish: 2 changes by joeax910
chinese (traditional): 2 changes by KogentaSan
english (us): 4 changes by 2TallTyler
chinese (simplified): 2 changes by WenSimEHRP
finnish: 2 changes by hpiirai
Bridges above stations will have pillars excluded if they conflict with the station layout.
Partly based on the system implemented in JGRPP.
Co-authored-by: <su@angel-island.zone>
english (au): 2 changes by krysclarke
norwegian (bokmal): 7 changes by eriksorngard
chinese (traditional): 2 changes by KogentaSan
korean: 7 changes by telk5093
russian: 2 changes by Ln-Wolf
catalan: 24 changes by J0anJosep
portuguese (brazilian): 2 changes by pasantoro
polish: 2 changes by pAter-exe
english (au): 2 changes by krysclarke
chinese (simplified): 4 changes by WenSimEHRP
finnish: 2 changes by hpiirai
french: 52 changes by glx22
portuguese: 2 changes by jcteotonio
portuguese (brazilian): 2 changes by pasantoro
polish: 2 changes by pAter-exe
Bridges can now include information about pillars and blocked edges for each bridge piece.
This data is set for default bridges, and NewGRFs can provide their own pillar information.
english (au): 2 changes by krysclarke
chinese (traditional): 2 changes by KogentaSan
english (us): 4 changes by 2TallTyler
chinese (simplified): 2 changes by WenSimEHRP
greek: 2 changes by gh658804
portuguese (brazilian): 2 changes by pasantoro
polish: 2 changes by pAter-exe
english (au): 1 change by krysclarke
norwegian (bokmal): 1 change by eriksorngard
chinese (traditional): 2 changes by KogentaSan
greek: 1 change by gh658804
hungarian: 1 change by vargaviktor
german: 190 changes by Wuzzy2
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
portuguese (brazilian): 1 change by pasantoro
polish: 3 changes by pAter-exe
swedish: 55 changes by robert-i
norwegian (bokmal): 8 changes by eriksorngard
spanish (mexican): 1 change by absay
chinese (simplified): 1 change by WenSimEHRP
english (au): 5 changes by krysclarke
chinese (traditional): 7 changes by KogentaSan
chinese (simplified): 11 changes by WenSimEHRP
korean: 5 changes by telk5093
greek: 7 changes by gh658804
hungarian: 5 changes by vargaviktor
russian: 7 changes by Ln-Wolf
finnish: 5 changes by hpiirai
portuguese: 5 changes by jcteotonio
portuguese (brazilian): 5 changes by pasantoro
polish: 6 changes by pAter-exe
english (au): 6 changes by krysclarke
chinese (traditional): 8 changes by KogentaSan
spanish (mexican): 6 changes by absay
greek: 6 changes by gh658804
hungarian: 6 changes by vargaviktor
russian: 6 changes by Ln-Wolf
finnish: 6 changes by hpiirai
portuguese: 6 changes by jcteotonio
portuguese (brazilian): 6 changes by pasantoro
Move various base offsets to separate functions where they can be reused and documented.
No longer rely on coincidences to select the correct data between bridges and aqueducts.
english (au): 5 changes by krysclarke
korean: 6 changes by telk5093
greek: 5 changes by gh658804
russian: 5 changes by Ln-Wolf
finnish: 5 changes by hpiirai
portuguese: 5 changes by jcteotonio
portuguese (brazilian): 5 changes by pasantoro
Lots of different structs contain variations on sub-tile bounds with different naming. Unify into a single struct that can be inherited and passed directly to AddSortableSpriteToDraw.
At the same time, offsets now work more logically: sub-tile bounds now specify the bounding box, and an offset can be applied to the sprite.
Records amount of cargo accepted, and a rolling average of the waiting amount.
Average waiting samples the waiting amount once per day for each industry, spread out over an economy day.
Resolved by removing the Build Industry command callback. This was used to display an error message in the scenario editor, however an error is already automatically displayed.
chinese (traditional): 1 change by KogentaSan
greek: 1 change by gh658804
hungarian: 1 change by vargaviktor
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
catalan: 49 changes by J0anJosep
portuguese: 2 changes by jcteotonio
portuguese (brazilian): 1 change by pasantoro
polish: 1 change by pAter-exe
Each font cache implementation sets its own metrics based on the loaded font, so there is no need to pre-fill with (unscaled, invalid) default metrics.
spanish (mexican): 1 change by absay
english (us): 1 change by 2TallTyler
galician: 10 changes by pvillaverde
dutch: 1 change by Afoklala
portuguese: 10 changes by jcteotonio
english (au): 1 change by krysclarke
chinese (traditional): 1 change by KogentaSan
chinese (simplified): 1 change by WenSimEHRP
korean: 1 change by telk5093
greek: 1 change by gh658804
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
portuguese: 1 change by azulcosta
portuguese (brazilian): 1 change by pasantoro
polish: 1 change by pAter-exe
english (au): 3 changes by krysclarke
korean: 6 changes by telk5093
greek: 3 changes by gh658804
russian: 3 changes by Ln-Wolf
dutch: 6 changes by Afoklala
portuguese: 4 changes by jcteotonio
portuguese (brazilian): 3 changes by pasantoro
english (au): 6 changes by krysclarke
greek: 7 changes by gh658804
russian: 6 changes by Ln-Wolf
finnish: 25 changes by hpiirai
portuguese: 19 changes by jcteotonio
portuguese (brazilian): 6 changes by pasantoro
polish: 6 changes by pAter-exe
When the string codes CARGO_TINY, CARGO_SHORT or CARGO_LONG encountered an out-of-range string, they did not read the extra amount parameter. This leads to later parameters being used in the wrong place.
Change the order of operation so that all parameters for these string codes are always read, even if the cargo type is not valid.
This now returns an iterator, and whether an insert was performed.
Allows the caller to know if the item was already in the FlatSet without explicitly checking first.
english (au): 8 changes by krysclarke
chinese (traditional): 23 changes by KogentaSan
chinese (simplified): 12 changes by WenSimEHRP
greek: 8 changes by gh658804
russian: 6 changes by Ln-Wolf
finnish: 8 changes by hpiirai
portuguese: 9 changes by jcteotonio
portuguese (brazilian): 8 changes by pasantoro
english (au): 4 changes by krysclarke
norwegian (bokmal): 4 changes by eriksorngard
chinese (traditional): 4 changes by KogentaSan
korean: 4 changes by telk5093
greek: 4 changes by gh658804
hungarian: 4 changes by vargaviktor
russian: 4 changes by Ln-Wolf
finnish: 4 changes by hpiirai
portuguese: 4 changes by jcteotonio
portuguese (brazilian): 4 changes by pasantoro
Bits used by company faces are now defined by a variable system instead of being hardcoded, allowing future expansion.
The four face types covering gender and skin colour are now separate face styles with their own definitions.
In most places where we calculate and set widget resize step we neglect
to set widget fill step to match. Initial widget sizing uses fill step
instead of resize step, which means the initial size may not be a
multiple of the resize step as intended. In particular this will cause
WWT_MATRIX to be misrendered.
Whether or not this matters depends on the widget type being resized and
the window layout, however for consistency always set fill step to the
same as resize step when calculating.
chinese (traditional): 4 changes by KogentaSan
chinese (simplified): 69 changes by WenSimEHRP
ukrainian: 57 changes by StepanIvasyn
portuguese: 35 changes by jcteotonio
This could happen if the compatibility between the railtypes was not symmetric. If for
example a reservation of a first train ended at a railtype transition with an already present
reservation on the other side, a reversing train could end up crashing with the first train.
chinese (traditional): 3 changes by KogentaSan
chinese (simplified): 108 changes by WenSimEHRP
ukrainian: 21 changes by StepanIvasyn
dutch: 9 changes by Afoklala
portuguese: 177 changes by jcteotonio
This is equivalent in functionality to ReferenceThroughBaseContainer,
except only for the correct index type, instead of any type matching
ConvertibleThroughBase.
The also serves to unambiguously document the index type at the
point of definition of the container.
hungarian: 9 changes by vargaviktor
finnish: 13 changes by hpiirai
ukrainian: 1 change by imlystyi
tamil: 2 changes by merni-ns
lithuanian: 1 change by khamper
spanish: 22 changes by Unely
portuguese: 46 changes by jcteotonio
english (au): 9 changes by krysclarke
spanish (mexican): 10 changes by absay
english (us): 9 changes by 2TallTyler
korean: 13 changes by telk5093
lithuanian: 3 changes by khamper
portuguese: 13 changes by jcteotonio
polish: 9 changes by pAter-exe
chinese (traditional): 9 changes by KogentaSan
greek: 9 changes by gh658804
russian: 9 changes by Ln-Wolf
portuguese (brazilian): 9 changes by pasantoro
english (au): 4 changes by krysclarke
spanish (mexican): 3 changes by absay
greek: 4 changes by gh658804
hungarian: 4 changes by vargaviktor
russian: 5 changes by Ln-Wolf
dutch: 4 changes by Afoklala
portuguese (brazilian): 4 changes by pasantoro
polish: 4 changes by pAter-exe
spanish (mexican): 4 changes by absay
chinese (simplified): 4 changes by WenSimEHRP
hungarian: 5 changes by vargaviktor
french: 27 changes by glx22
polish: 4 changes by pAter-exe
english (au): 4 changes by krysclarke
chinese (traditional): 5 changes by KogentaSan
english (us): 5 changes by 2TallTyler
greek: 4 changes by gh658804
russian: 4 changes by Ln-Wolf
finnish: 4 changes by hpiirai
latvian: 6 changes by lexuslatvia
portuguese: 4 changes by jcteotonio
portuguese (brazilian): 4 changes by pasantoro
norwegian (bokmal): 1 change by eriksorngard
spanish (mexican): 1 change by absay
chinese (simplified): 1 change by WenSimEHRP
korean: 1 change by telk5093
danish: 68 changes by bscargo
Removes the orders pool, and orders are now stored directly in each OrderList.
Iterating orders now no longer needs to traverse a linked-list, all orders in an OrderList are sequential.
Measuring the name width did not also take account of indentation levels so didn't prevent cropping, and the window can be resized anyway.
This avoids a potential bottleneck due to layouting group names if there are a lot of groups present.
* Add: [Script] GSBaseStation::GetOwner
Added method for Game Scripts to retrieve the owner of a basestation.
* Cleanup: [Script] Remove ScriptStation::GetOwner
Due to class inheritance, GSStation::GetOwner and GSWaypoint::GetOwner can both reach GetOwner defined at GSBaseStation.
english (au): 1 change by krysclarke
chinese (traditional): 10 changes by KogentaSan
greek: 1 change by gh658804
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
latvian: 1 change by lexuslatvia
portuguese: 1 change by jcteotonio
portuguese (brazilian): 1 change by pasantoro
polish: 10 changes by pAter-exe
english (au): 2 changes by krysclarke
chinese (traditional): 2 changes by KogentaSan
spanish (mexican): 2 changes by absay
chinese (simplified): 11 changes by WenSimEHRP
greek: 2 changes by gh658804
hungarian: 2 changes by vargaviktor
persian: 17 changes by realsepehrz
russian: 2 changes by lexuslatvia
finnish: 4 changes by hpiirai
latvian: 2 changes by lexuslatvia
portuguese (brazilian): 2 changes by pasantoro
Refresh company finance windows via a WindowTimer instead of in game loop.
As the invalidation affects multiple windows this is a global timer instead of window-specific.
When configuring NewGRFs outside of a game, the changes are always applied when the window is closed, even if the Apply button is not used.
The Apply button only needs appear during a game when changes are not automatically applied.
chinese (traditional): 1 change by KogentaSan
chinese (simplified): 1 change by WenSimEHRP
greek: 1 change by gh658804
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
dutch: 8 changes by Afoklala
portuguese: 3 changes by jcteotonio
portuguese (brazilian): 1 change by pasantoro
polish: 1 change by pAter-exe
Normally DrawStringMultiLine does not perform any clipping, as the return value may be needed if it the text is not drawn.
In some specific cases the height is already known, so it is possible to test for clipping, which can cut down on layouting time for text which won't be visible.
english (au): 2 changes by krysclarke
chinese (traditional): 3 changes by KogentaSan
chinese (simplified): 6 changes by WenSimEHRP
greek: 2 changes by gh658804
russian: 2 changes by Ln-Wolf
finnish: 3 changes by hpiirai
portuguese (brazilian): 2 changes by pasantoro
polish: 2 changes by pAter-exe
english (au): 4 changes by krysclarke
norwegian (bokmal): 5 changes by eriksorngard
chinese (traditional): 4 changes by KogentaSan
greek: 8 changes by gh658804
russian: 4 changes by Ln-Wolf
finnish: 4 changes by hpiirai
portuguese: 4 changes by jcteotonio
portuguese (brazilian): 4 changes by pasantoro
polish: 4 changes by pAter-exe
NewGRF Action 11 should be handled in both INIT and ACTIVATION stages for sounds to be loaded.
Additionally the Action 0 feature test failed due to offsets involved.
english (au): 1 change by krysclarke
chinese (traditional): 1 change by KogentaSan
galician: 66 changes by pvillaverde
chinese (simplified): 1 change by WenSimEHRP
korean: 72 changes by telk5093
greek: 1 change by gh658804
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
Use the normal or lightest colour gradient to pick a suitable colour, instead of an arbitrary pixel colour.
(Except for the NewGRF window's info panel, this happens to be the same colour.)
The bucket selection uses a truncating division instead of a flooring division, so it does not work for negative positions.
Anyhow, there are no negative tile coordinates, so just clamp the search area.
During each game tick every cargo payment will issue an Invalidate of the status bar and company finance window. While this doesn't paint the window yet, it does need to search for open windows, and then mark a area of dirty blocks, which is done for every Invalidate.
Instead, set a bit in a CompanyMask, and test these bits once after the game tick is complete.
This reduces the amount of dirtying, and allows more specific widgets to be dirtied instead of the whole window.
chinese (traditional): 9 changes by KogentaSan
english (us): 66 changes by 2TallTyler
greek: 65 changes by gh658804
russian: 77 changes by Ln-Wolf
dutch: 66 changes by Afoklala
portuguese: 65 changes by jcteotonio
polish: 68 changes by pAter-exe
english (au): 65 changes by krysclarke
norwegian (bokmal): 67 changes by eriksorngard
chinese (traditional): 67 changes by KogentaSan
spanish (mexican): 66 changes by absay
chinese (simplified): 91 changes by WenSimEHRP
finnish: 65 changes by hpiirai
french: 61 changes by ottdfevr
portuguese (brazilian): 65 changes by pasantoro
Previous minimum width of 400 was fairly arbitrary and isn't necessary when
the minimum size is suitably constrained by other widgets in the window.
This allows the window to be narrower for CJK languages.
english (au): 1 change by krysclarke
chinese (traditional): 7 changes by KogentaSan
chinese (simplified): 201 changes by WenSimEHRP
greek: 1 change by gh658804
hungarian: 9 changes by meskobalazs
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
latvian: 1 change by lexuslatvia
portuguese: 1 change by azulcosta
portuguese (brazilian): 1 change by pasantoro
polish: 1 change by pAter-exe
In the depot, when dragging a train over another train, the tile length displayed now includes the length of the dragged train.
As the parts are not moved yet, length changes due to callbacks are not taken into account.
This improves usability when toggling content sorted by status, as the list position no longer jumps to the now (de)selected item, making it easier to (de)select multiple items.
Company infrastructure window will no longer overflow the screen when lots of rail and road types are present.
To further declutter the list, we now only show a value when the count for that item is non-zero.
String parameters are always stored as uint64_t. Negative values are sign-extended to int64_t and then casted to uint64_t.
The same applies to encoded strings. But ScriptText encoded them as int64_t.
Co-authored-by: rubidium42 <rubidium42@users.noreply.github.com>
VehicleEnterTileStatus was an bitset-style enum, but bitstuffed with a StationID. However the StationID part was only used by trains, and only in two locations.
Instead, return just the enum bitset. The two places which require the StationID just call GetStationIndex() directly.
This occurs because the extra invalidation in OnInit() also happens on construction, and too early.
Solution is to validate all instead of just position when invalidating in OnInit().
After loading airports+tiles, industries+tiles, houses and objects, their specs are copied from the NewGRF's loading storage to the final global storage.
Instead, move the specs to the their new storage, and clear the NewGRF's storage once done. (Stations and RoadStops are different, and the NewGRF's storage is the final storage location.)
Unnamed badges are intended to be for internal-use, not for player information.
Additionally if there is no name to the class, then is causes problems when user configuration comes.
Instead of requesting content one ID at a time, queue them up to be requested in one go.
* Avoids sending many small requests.
* Avoids sending requests for content which is likely to be arriving anyway.
english (au): 1 change by krysclarke
chinese (simplified): 1 change by WenSimEHRP
greek: 1 change by gh658804
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
portuguese (brazilian): 1 change by pasantoro
polish: 4 changes by pAter-exe
These functions no longer clean up manually managed memory, they simply clear GRFFile's vectors of unique_ptrs. This will happen anyway when the GRFFile is deleted.
With CMake 4.0.0, any project < 3.5 is no longer supported. Yet,
some projects indicate 3.0 or 3.1 (while fully compatible with
3.5+). But CMake doesn't know, so it bails.
OpenGFX for the other platforms is untar'd. There is no real need
to do this, but there is also no hurt in not doing it. And doing
the same for all three has more benefits than having one being
different.
chinese (traditional): 1 change by KogentaSan
vietnamese: 11 changes by KhoiCanDev
chinese (simplified): 10 changes by WenSimEHRP
french: 2 changes by ottdfevr
Specialisations seem to be the correct way to specialise, rather than redefining the base template.
This removes a macro which instantiated methods individually.
Each cache is ~1GB. And you can only have 10GB of cache. So after
10 runs, our cache is full of trap caches.
The kicker? We don't actually benefit from this cache. It is only
used if you re-run CodeQL over the exact same codebase (without
changes), to quickly re-evaluate the latest CodeQL set. We are
way to active to have any benefit from that, and we don't run
CodeQL on a schedule to ever pick up on the cache.
swedish: 89 changes by joeax910
norwegian (bokmal): 51 changes by eriksorngard
chinese (traditional): 1 change by KogentaSan
spanish (mexican): 195 changes by absay
chinese (simplified): 1 change by WenSimEHRP
finnish: 1 change by hpiirai
english (au): 8 changes by krysclarke
chinese (traditional): 5 changes by KogentaSan
spanish (mexican): 14 changes by absay
english (us): 2 changes by 2TallTyler
chinese (simplified): 4 changes by WenSimEHRP
greek: 2 changes by gh658804
russian: 14 changes by Ln-Wolf
finnish: 2 changes by hpiirai
portuguese: 2 changes by azulcosta
portuguese (brazilian): 2 changes by pasantoro
polish: 2 changes by pAter-exe
chinese (traditional): 8 changes by KogentaSan
spanish (mexican): 36 changes by absay
english (us): 19 changes by 2TallTyler
chinese (simplified): 5 changes by WenSimEHRP
greek: 6 changes by gh658804
finnish: 6 changes by hpiirai
french: 63 changes by glx22
portuguese: 5 changes by azulcosta
portuguese (brazilian): 6 changes by pasantoro
polish: 6 changes by pAter-exe
english (au): 13 changes by krysclarke
chinese (traditional): 15 changes by KogentaSan
spanish (mexican): 2 changes by absay
chinese (simplified): 2 changes by WenSimEHRP
greek: 13 changes by gh658804
finnish: 2 changes by hpiirai
portuguese: 31 changes by jcteotonio, 2 changes by azulcosta
portuguese (brazilian): 1 change by pasantoro
polish: 5 changes by pAter-exe
chinese (traditional): 61 changes by KogentaSan
spanish (mexican): 35 changes by absay
chinese (simplified): 16 changes by WenSimEHRP
russian: 13 changes by Ln-Wolf
finnish: 13 changes by hpiirai
catalan: 9 changes by J0anJosep
portuguese: 10 changes by azulcosta, 3 changes by jcteotonio
portuguese (brazilian): 13 changes by pasantoro
polish: 13 changes by pAter-exe
english (au): 3 changes by krysclarke
chinese (traditional): 6 changes by KogentaSan
spanish (mexican): 73 changes by absay
english (us): 43 changes by 2TallTyler
chinese (simplified): 3 changes by WenSimEHRP
greek: 3 changes by gh658804
finnish: 6 changes by hpiirai
portuguese: 3 changes by azulcosta
portuguese (brazilian): 3 changes by pasantoro
polish: 6 changes by pAter-exe
chinese (traditional): 37 changes by KogentaSan
spanish (mexican): 1 change by absay
chinese (simplified): 3 changes by WenSimEHRP
catalan: 38 changes by J0anJosep
portuguese: 42 changes by azulcosta
polish: 4 changes by pAter-exe
english (au): 39 changes by krysclarke
chinese (traditional): 66 changes by KogentaSan
spanish (mexican): 65 changes by absay
chinese (simplified): 97 changes by WenSimEHRP
greek: 39 changes by gh658804
russian: 42 changes by Ln-Wolf
finnish: 39 changes by hpiirai
portuguese (brazilian): 39 changes by pasantoro
polish: 52 changes by pAter-exe
Order display is now composed of concatenated strings instead of a complex 10-parameter format string, which simplifies things and fixes duplicate spaces.
Sometimes the bottom is passed as UINT16_MAX for no reason. In this case just pass the rect.
Other times it's to extend the window height; in that case just extend the rect itself.
spanish (mexican): 9 changes by absay
galician: 30 changes by pvillaverde
chinese (simplified): 1 change by WenSimEHRP
catalan: 1 change by J0anJosep
latvian: 30 changes by lexuslatvia
dutch: 4 changes by Afoklala
english (au): 1 change by krysclarke
chinese (traditional): 1 change by KogentaSan
spanish (mexican): 3 changes by absay
greek: 1 change by gh658804
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
portuguese: 1 change by azulcosta
portuguese (brazilian): 1 change by pasantoro
polish: 1 change by pAter-exe
english (au): 3 changes by krysclarke
norwegian (bokmal): 4 changes by eriksorngard
chinese (traditional): 4 changes by KogentaSan
spanish (mexican): 67 changes by absay
english (us): 4 changes by 2TallTyler
chinese (simplified): 54 changes by WenSimEHRP
arabic (egypt): 77 changes by ImMorrow
greek: 3 changes by gh658804
russian: 3 changes by Ln-Wolf
finnish: 3 changes by hpiirai
portuguese: 3 changes by azulcosta
portuguese (brazilian): 3 changes by pasantoro
polish: 3 changes by pAter-exe
english (au): 1 change by krysclarke
chinese (traditional): 1 change by KogentaSan
spanish (mexican): 264 changes by absay
greek: 1 change by gh658804
russian: 2 changes by Ln-Wolf
finnish: 1 change by hpiirai
portuguese: 1 change by jcteotonio
portuguese (brazilian): 1 change by pasantoro
polish: 4 changes by pAter-exe
Width for all spacers was included only due to an off-by-one from counting buttons and not excluding the normally hidden switcher button.
Spacer width of quarter the button width is now included explicitly,
Trees are now placed in irregular blob shapes instead of repetitive diamond shapes.
---------
Co-authored-by: Susan <su+git@angel-island.zone>
Co-authored-by: Peter Nelson <peter1138@openttd.org>
english (au): 14 changes by krysclarke
chinese (traditional): 14 changes by KogentaSan
english (us): 14 changes by 2TallTyler
vietnamese: 3 changes by KhoiCanDev
greek: 14 changes by gh658804
russian: 16 changes by Ln-Wolf
finnish: 14 changes by hpiirai
portuguese: 14 changes by azulcosta
portuguese (brazilian): 15 changes by pasantoro
polish: 12 changes by pAter-exe
This allows a string and its parameters to be encoded and stored as just one string, instead of juggling with capturing and restoring string parameters.
The advantage of EncodedStrings over raw strings is they use current language and parameter values at the point of decoding.
std::numeric_limits<T>::max() returns 0 instead of an error when the type is unknown.
Solve it by implementing and using Set() and All() in BaseBitSet in same way as std::bitset.
When generating maps or loading heightmaps, the terrain height is altered to prevent slopes that can't be represented.
During this, there is now a chance of these tiles being turned into a rocky tile.
Chance of placing rocks is based on the height. This gives a rocky mountain appearance without affecting all peaks.
Also remove some of the artifical documented limits as they are not true; the
ClientPoolID was not sent over the network, so its size isn't of concern.
- compat_NNN.nut files now only defines what is needed to downgrade from API NNN + 1 to NNN.
- Automatically load all required compatibility files based on the API version of the script, starting with the latest.
A Source is either a CompanyID (Headquarters), IndustryID or TownID.
When making those types stronger a lot of casts would be needed, but
with these simple helpers the intent is shown more clearly.
This provides support for ConvertibleThroughBase positions passed to the
functions of a container that return a reference, specifically 'at(pos)'
and 'operator[](pos)'.
In the script's API `COMPANY_INVALID` has a value of -1, whereas the internal
game's `INVALID_COMPANY` has a value of 255. Since the script's API also has
a `COMPANY_SPECTATOR` with a value of 255, these enumerations cannot be easily
reconciled by casting. As such, replace all casts in the script API with
either ScriptCompany::FromScriptCompanyID or ScriptCompany::ToScriptCompanyID.
Also make clear whether CompanyID is ::CompanyID or ScriptCompany::CompanyID
by using either one of those over CompanyID in the script's API.
ArrayStringParameters contains extra state that is used when formatting strings which isn't needed when creating parameter lists.
MakeParameters() now returns a std::array which contains only the parameter data. This simpler container is more widely available than before.
A DestinationID is either a DepotID or StationID, where the aircraft hangar
being conceptually a depot is actually a StationID. When making those types
stronger, a lot of casts would need to be added, but this shows the intent
much better.
english (au): 6 changes by krysclarke
chinese (traditional): 8 changes by KogentaSan
spanish (mexican): 3 changes by absay
greek: 12 changes by gh658804
russian: 12 changes by Ln-Wolf
finnish: 8 changes by hpiirai
catalan: 8 changes by J0anJosep
portuguese: 9 changes by azulcosta
portuguese (brazilian): 8 changes by pasantoro
polish: 14 changes by pAter-exe
english (au): 1 change by krysclarke
chinese (traditional): 2 changes by KogentaSan
spanish (mexican): 1 change by absay
russian: 2 changes by Ln-Wolf
catalan: 3 changes by J0anJosep
english (au): 1 change by krysclarke
chinese (traditional): 3 changes by KogentaSan
chinese (simplified): 3 changes by WenSimEHRP
greek: 1 change by gh658804
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
portuguese: 1 change by azulcosta
portuguese (brazilian): 1 change by pasantoro
polish: 3 changes by pAter-exe
english (au): 2 changes by krysclarke
norwegian (bokmal): 2 changes by eriksorngard
spanish (mexican): 9 changes by absay
greek: 2 changes by gh658804
russian: 2 changes by Ln-Wolf
finnish: 2 changes by hpiirai
portuguese: 2 changes by azulcosta
portuguese (brazilian): 2 changes by pasantoro
polish: 2 changes by pAter-exe
This makes it possible to write templated alternatives for ConvertibleThroughBase
which are then available for any (strong) type that implements a base() function
In the end making adding new ConvertibleThroughBase types less awkward.
-fno-tree-vrp is essentially a GCC implementation detail which controls
a powerful source of optimisation information. The linked GCC bug from 2010(!)
shows that -fno-strict-enums was added in response to the bug report, and
we can use that instead. Clang supports it too. Use that instead for both
GCC and (newly) Clang.
chinese (traditional): 1 change by KogentaSan
chinese (simplified): 3 changes by WenSimEHRP
catalan: 1 change by J0anJosep
polish: 1 change by pAter-exe
english (au): 1 change by krysclarke
norwegian (bokmal): 1 change by eriksorngard
english (us): 1 change by 2TallTyler
greek: 1 change by gh658804
finnish: 1 change by hpiirai
portuguese: 1 change by jcteotonio
portuguese (brazilian): 1 change by pasantoro
This is only available from C++23, but the implementation is fairly trivial
and the old variants of BSWAP32/BSWAP16 were not constexpr on MSVC. This was
due to all kinds of intrinsics that were added to get better code. However,
recent compilers with reasonable optimisation settings see the naive code and
will inject the appropriate optimised code (bswap op on x86-64).
For x86-64 recent is: Clang 6+ -O1, GCC 6+ -O2, MSVC 19.34+ /O1.
`TTD_ENDIAN` is used to change the order of the r,g,b,a members of `Colour` to suit the architecture.
This kind of conditional is not supported by C++/`std::endian`, so instead three separate Colour unions are defined, `ColourRGBA`, `ColourARGB` and `ColourBGRA`. The correct union is then aliased to `Colour` using `std::conditional`.
Change the sprite drawing order defined by the enum and table to draw the (shirt) collar first, under the jacket. Simplifies new graphics development, allowing the shirt collar sprite to be a full shirt.
When opening vehicle lists a static WindowDesc is modified to change the class depending on the vehicle type.
Theses makes for inconsistencies and preferred window state, and prevents WindowDesc members being made const.
Due to function overloads and default parameters, the wrong `NWidget()` function was called, resulting resulting in the wrong `NWidgetPart` being created.
This uses nearest colour lookup to convert 32bpp-only sprites to indexed 8bpp on the fly. This provides a reasonable usable sprite instead of being incompatible.
Now that SkipGarbage doesn't skip all multi-byte utf-8 characters, string control codes are not skipped either. This gave unintended sorting when NewGRF names start with colour codes.
Use StrMakeValid() before comparing. This has to make a copy of the string for each sort step, so there is likely a performance penalty.
english (au): 5 changes by krysclarke
norwegian (bokmal): 8 changes by eriksorngard
chinese (simplified): 5 changes by WenSimEHRP
korean: 5 changes by telk5093
greek: 5 changes by gh658804
russian: 5 changes by Ln-Wolf
finnish: 5 changes by hpiirai
portuguese (brazilian): 5 changes by pasantoro
polish: 5 changes by pAter-exe
english (au): 3 changes by krysclarke
spanish (mexican): 6 changes by absay
greek: 3 changes by gh658804
hebrew: 127 changes by yair-bn
finnish: 3 changes by hpiirai
catalan: 3 changes by J0anJosep
portuguese: 3 changes by azulcosta
portuguese (brazilian): 3 changes by pasantoro
polish: 3 changes by pAter-exe
One of the features of cheats is that there is a record of a cheat being used.
As cheats are slowly ending up in settings instead, add a flag so that changes to these sandbox settings are logged.
This allows cargo packets and cargo flow data to be empty if not in use, which is the case for the majority of station goods entries, and data is allocated when needed.
This reduces the initial size of a Station from 9192 bytes to 2024 bytes (on 64 bit platforms), although an allocation of 120 bytes is made for each active cargo type at a station.
Based on similar changes in JGRPP.
When drawing viewport strings, the StringID is used to determine how to draw the sign. Instead, allow the behaviour to be set by the caller with flags. This means that some of the viewport-specific strings are no longer necessary.
ViewportAddString() now returns a pointer to a string as it may not actually add the string, in which case preparing the string parameters in advance is a waste of time.
Set colour for these widget types to INVALID_COLOUR to avoid giving the impression that the colour has a purpose.
A runtime exception is added to catch this the existing widget unit test.
Rail station tile flags now use bits that were (long ago) used to store railtype.
During Afterload, there are some calls that need the state of station tile flags to be correct which were executed before the station tile flags were set.
When allowed to found towns in game, some buttons are disabled as they are only available in the scenario editor.
Instead of disabling these buttons, completely hide them when in game.
Use a base multiplier to keep the existing option range (1-15).
SDL2 >= 2.18 allows for considerably smoother scrolling, but
basic support for earlier versions is included.
chinese (traditional): 10 changes by KogentaSan
galician: 9 changes by pvillaverde
korean: 9 changes by telk5093
russian: 10 changes by Ln-Wolf
polish: 1 change by pAter-exe
Small viewport signs are drawn with FS_SMALL, so there is no need to duplicate text effect strings for both normal and small versions.
This also avoids an extra string format when text effect positions are updated.
english (au): 1 change by krysclarke
norwegian (bokmal): 8 changes by eriksorngard
chinese (simplified): 1 change by WenSimEHRP
greek: 1 change by gh658804
russian: 52 changes by Ln-Wolf
finnish: 1 change by hpiirai
french: 1 change by glx22
portuguese: 1 change by azulcosta
portuguese (brazilian): 1 change by pasantoro
If string parameters are not set correctly, FormatString can read out of bounds and crash the game.
This does not fix the root cause, just a nasty symptom.
When a NewGRF overrides another, any translation table that the overriding NewGRF installs will also be installed in the target file.
This allows the overridden NewGRF to make use of a cargo or rail/road type translation table without directly modifying the original file.
Sounds are loaded into memory on first use, using the SoundLoader interface to support format conversion. Sounds are retained in memory to avoid reloading every time a sound is played.
This deduplicates WAV header parsing between NewGRF and baseset sounds, and will allow different audio formats to be supported.
english (au): 8 changes by krysclarke
greek: 8 changes by gh658804
russian: 8 changes by Ln-Wolf
finnish: 8 changes by hpiirai
french: 11 changes by glx22
portuguese (brazilian): 8 changes by pasantoro
polish: 8 changes by pAter-exe
Allows quickly finding the EngineID given the type, grfid and local id of an engine, instead a linear scan.
This can reduce loading time when lots of engines are present and also affects performance in-game.
Lookup can be on the order of 10000 times faster.
The pointer was already captured and converted to a unqiue_ptr, but hidden within the call stack.
This now makes it clearer that the object passed to Add.*NewsItem will become owned by the news item.
Engines defined outside the original range did not have their cargo type/cargo label fields initialised properly.
If these engines are also not assigned a cargo type, they would therefore use the cargo in slot 0 instead of falling back to first refittable.
This allows animated tiles to be added and removed without searching in the animated tile list, providing a performance improvement when there are lots of animated tiles.
Save game version is bumped so that animated tile state can be converted.
All GRFConfigs have space allocated for parameters, but only configured GRFConfigs need them.
Using a vector instead means that space is only used when parameters are used.
* Use appropriate container widget nesting with padding, instead of single-sided padding.
* Use layer widget to allow main news message to overlay close box and date widgets, to more closely match the old fixed-pixel layout.
Each callback result requires a pool memory allocation, each of which is 24 bytes.
Build a cache of results so that if the same result is used later it refers to the same group.
This solves finances not being show if the company inauguration date is in the future.
Current period is now always shown in the same position instead of moving for the first 2 years.
When there are many more items than fit in a list, the scrollbar slider scales to fit but there is no minimum size. It becomes too small to click on and use.
Ensure scrollbar slider is at least the same size as the buttons either end.
When rebuilding the industry directory list, the width of every item in the list is obtained to get the maximum width required for the horizontal scrollbar. This can take considerable time if there are a lot of industries.
Instead, calculate only for the visible rows, and grow as needed.
english (au): 2 changes by krysclarke
swedish: 4 changes by joeax910
chinese (traditional): 2 changes by KogentaSan
chinese (simplified): 3 changes by WenSimEHRP
greek: 4 changes by gh658804
russian: 3 changes by Ln-Wolf
finnish: 4 changes by hpiirai
portuguese (brazilian): 3 changes by pasantoro
polish: 46 changes by pAter-exe
Recolour sprites are loaded when seen, instead of being loaded when needed. This could result in the sprite cache being filled up with recolour sprites, and also mean that replacing recolour sprites didn't release the previously allocated memory.
Instead, allow recolour sprites to be loaded as needed and freed when unneeded, like regular sprites.
Use member-initialisation, reorder members to reduce space, and prefer references.
SetValue/GetValue are moved to GRFConfig as they set the config's parameter values.
english (au): 1 change by krysclarke
chinese (traditional): 1 change by KogentaSan
korean: 5 changes by telk5093
greek: 1 change by gh658804
dutch: 1 change by KevinHeijsteeg2
Store a list of industries per industry type. This allows industry generation checks which only consider a specific industry type to check a reduced set of industries, leading to a potential performance increase.
This also removes the need to track industry type counts as well.
Kdtree uses a function pointer and incorrectly calls it a functor. The function pointer needs to be passed on instantiaton.
Instead, use an actual functor. This simplifies instantiation.
Ship and RoadVehicle path caches use a std::deque, which is quite memory hungry, especially for RoadVehicle which has two.
std::deque was used to be able to push/pop from either end.
Change to use a single std::vector each, which is now push/popped from the back.
IndustrySpec and IndustryTileSpec cargo label lists are only used for original industries. Original industries can only have up to 2 inputs and 3 outputs. Therefore having space for 16 input/outputs slots is unnecessary
This saves 216 bytes per industry type, and 164 bytes per industry tile type.
* After double-clicking on a location button to follow a vehicle, show that state by drawing the location button in a lowered state.
* Allow cancelling the follow state by clicking on the location button again.
This allows water tiles which cannot flood any further to not even try to flood.
On a large map with lots of water tiles this can noticeably reduce game loop processing time.
Mostly ported from JGRPP.
Build the list of railtype conversions at the same time as testing if conversion is needed.
This avoids having two similar loops which need to compare the same things.
CargoPayment required cargo type to be set as state via SetCargo(). This was error prone as CargoPayment is per consist but cargo type can vary per vehicle part. Additionally if SetCargo was not called then the default "uninitialised" state was cargo slot 0, passengers.
Instead of trying to make sure it is set correctly, remove cargo type from CargoPayment and always pass it explicitly to the PayTransfer/PayFinalDelivery methods.
english (au): 4 changes by krysclarke
english (us): 4 changes by 2TallTyler
chinese (simplified): 4 changes by WenSimEHRP
greek: 4 changes by gh658804
russian: 4 changes by Ln-Wolf
dutch: 4 changes by Afoklala
portuguese: 4 changes by jcteotonio
portuguese (brazilian): 4 changes by pasantoro
Looking for label 0 would incorrectly return the first undefined type instead of INVALID_RAIL/ROADTYPE, which could potentially cause incorrect behaviour.
Now that SkipGarbage doesn't skip all multi-byte utf-8 characters, string control codes are not skipped either. This gave unintended sorting when NewGRF names start with colour codes.
Make SkipGarbage UTF-8 aware so that it is able to skip some unicode ranges as well.
Use index of last child instead of pointer to update next_child element.
In case there is no child sprite yet, the most recent parent sprite's first_child is updated instead.
Split AfterLoadVehicles into two functions.
Vehicle cache init and other functionality requiring an upgraded and
valid map is now performed later in the load process.
If the starting tile is near the edge of the map, the width and height could overflow the map boundary.
In some cases this might result in a different area being planted than expected.
This was originally generic and used by YAPF, but now it is used only by script objects.
CCountedPtr provided much more (untested) functionality than used.
ScriptObjectRef already exists for script objects and does the same thing, so use this instead.
While ubuntu-latest is transitioning from ubuntu-22.04 to ubuntu-24.04, the one we actually run on is random.
But our workflow can work only with 22.04 (using clang15) or 24.04 (using clang) so just force 24.04 for now.
Since SetDParamStr() always owns a copy of the string, there is no need to make another copy of it to keep it around while the news item exists.
This also fixes a leak in `CmdIndustrySetProduction` as the allocated data wasn't passed to AddIndustryNewsItem.
english (au): 4 changes by krysclarke
chinese (traditional): 18 changes by KogentaSan
greek: 4 changes by gh658804
italian: 11 changes by Boh132Boh
russian: 4 changes by Ln-Wolf
finnish: 5 changes by hpiirai
portuguese (brazilian): 4 changes by pasantoro
polish: 78 changes by pAter-exe
Instead of falling back to bitnum lookup or climate-dependent cargo types, install a default cargo translation table that performs either of these functions instead.
This allows better mapping of climate-dependent or bitnum cargo slots, falling back to INVALID_CARGO if they are not defined, and reduces special-casing.
In the refactor to unified tile animation code, the test for `CALLBACK_1A_RANDOM_BITS` incorrectly got changed to a `HasBit()` test preventing it from working.
Use `HasFlag()` instead.
english (au): 1 change by krysclarke
chinese (simplified): 1 change by WenSimEHRP
greek: 1 change by gh658804
russian: 1 change by Ln-Wolf
portuguese (brazilian): 1 change by pasantoro
Since initial colour is no longer passed to the text layout, TC_FORCED flag is not seen by the layouter, so it had no effect.
Instead, check for TC_FORCED when drawing and avoid using the string's colours if set.
This simplifies tests for `(x & y) != y` with enum classes by reducing repetition, similar to HasBit(), and also makes the intent of the expression clearer.
Using an actual random chance to generate cities means that there may be far less or far more than 'expected' towns being made as cities.
While this is the point of randomness, the wording of the setting is "Proporation of towns that will become cities: 1 in X" and does not mention randomness at all.
english (au): 1 change by krysclarke
english (us): 9 changes by 2TallTyler
galician: 13 changes by pvillaverde
korean: 9 changes by telk5093
greek: 1 change by gh658804
finnish: 1 change by hpiirai
lithuanian: 6 changes by isigitas
portuguese: 1 change by azulcosta
portuguese (brazilian): 1 change by pasantoro
polish: 1 change by aefoes
chinese (simplified): 9 changes by WenSimEHRP
catalan: 9 changes by J0anJosep
latvian: 1 change by lexuslatvia
french: 13 changes by glx22
portuguese: 9 changes by azulcosta
This allows longer parameters to be used in plural and gender commands.
Each individual word list parameter is now limited to 253 bytes, allowing for a trailing NUL and leaving 0xFF reserved.
english (au): 9 changes by krysclarke
greek: 9 changes by gh658804
russian: 9 changes by Ln-Wolf
finnish: 9 changes by hpiirai
latvian: 8 changes by lexuslatvia
portuguese (brazilian): 9 changes by pasantoro
This avoids storing two separate values and makes the test for which type is held clearer.
This replaces use of unique_ptr for conditionally storing a string, and is also used in place of StringParameterBackup.
english (au): 4 changes by krysclarke
greek: 4 changes by gh658804
russian: 4 changes by Ln-Wolf
finnish: 4 changes by hpiirai
polish: 4 changes by pAter-exe
* Codechange: Add AssignBit function to assign the value of a single bit
* Codechange: Replace various uses of SB with AssignBit
* Codechange: Replace various uses of SB with a constant with SetBit
english (au): 1 change by krysclarke
greek: 1 change by gh658804
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
portuguese (brazilian): 1 change by pasantoro
This avoids redundant tile refreshes when the caller has already marked a tile dirty, or knows it does not need refreshing.
Loosely backported from JGRPP.
The callers of DeleteAnimatedTile already know if the tile needs refreshing, so it is redundant for DeleteAnimatedTile to do so.
Loosely backported from JGRPP.
Timetable does not show vehicles as early, only as on time.
Fix this by changing 'VehicleIsAboveLatenessThreshold()' to
accept number of ticks the vehicle is late. This allows to
use it with absolute value.
Codefix #12860: Update comments
Co-authored-by: Tyler Trahan <tyler@tylertrahan.com>
BmpInfo width and height members are now size_t to avoid multiplication warnings.
This avoids manual memory management and allows BmpData to clean up after itself.
Properties 11, 14 and 15 to set pylons/nowires/blocked intrinsically only support 8 station tiles.
Add new property to define all three flags for each station tile layout.
Allow using up to 256 tile layouts in property 0E or callback 24, which defines the layout to be saved into the map.
This was originally limited to 8, because station graphics above 8 referred to other station types but that was changed in 2007.
1) More efficient than using callback 14, as that needs to be checked every time a station tile is rendered.
2) The layout does not get changed when the station is changed (this may or may not be desirable!)
Using more than 256 layouts still requires callback 14.
These callbacks both select rail station tile layouts, the difference is one happens when drawing, the other happens when building. Change the names to make this clearer.
Converting from UTF-8 to UTF-16 could have resulted in a buffer overflow if the buffer size was exactly the length of the converted string.
Pass string_view/span to convert_from/to_fs instead, and ensure the buffer is terminated. This replaces passing a pointer to the buffer and the buffer size as separate parameters, allowing the compiler to pass both in one parameter.
Removes use of `lengthof()`.
english (au): 1 change by krysclarke
swedish: 7 changes by joeax910
chinese (simplified): 2 changes by WenSimEHRP
korean: 1 change by telk5093
french: 2 changes by ottdfevr
english (au): 1 change by krysclarke
chinese (simplified): 2 changes by WenSimEHRP
greek: 1 change by gh658804
russian: 2 changes by Ln-Wolf
finnish: 1 change by hpiirai
catalan: 2 changes by J0anJosep
portuguese: 1 change by azulcosta
portuguese (brazilian): 1 change by pasantoro
polish: 1 change by pAter-exe
- Changing zoom no longer stops following vehicle
- Key scrolling while following a vehicle stops following
- Autoscrolling while following a vehicle stops following
- Main viewport can begin following a vehicle at any zoom
How missing glyphs were detected was changed, but the sprite font still substituted `?`, which to missing glyph looked like all characters are present.
english (au): 2 changes by krysclarke
english (us): 2 changes by 2TallTyler
chinese (simplified): 2 changes by WenSimEHRP
russian: 2 changes by Ln-Wolf
finnish: 25 changes by hpiirai
portuguese (brazilian): 2 changes by pasantoro
english (au): 10 changes by krysclarke
swedish: 13 changes by joeax910
english (us): 10 changes by 2TallTyler
chinese (simplified): 14 changes by WenSimEHRP
russian: 6 changes by Ln-Wolf
catalan: 14 changes by J0anJosep
latvian: 15 changes by lexuslatvia
portuguese (brazilian): 12 changes by pasantoro
english (au): 2 changes by krysclarke
norwegian (bokmal): 2 changes by eriksorngard
english (us): 2 changes by 2TallTyler
russian: 2 changes by Ln-Wolf
finnish: 2 changes by hpiirai
french: 2 changes by ottdfevr
portuguese (brazilian): 2 changes by pasantoro
polish: 2 changes by pAter-exe
For non-WWT_MATRIX widgets, scrollbars need to take account of the internal padding used for the widget.
This is not normally noticeable as framerect padding is only 2 extra pixels
english (au): 2 changes by krysclarke
norwegian (bokmal): 6 changes by eriksorngard
korean: 3 changes by telk5093
russian: 2 changes by Ln-Wolf
finnish: 3 changes by hpiirai
portuguese: 2 changes by azulcosta
portuguese (brazilian): 2 changes by pasantoro
polish: 5 changes by pAter-exe
NewGRFs only use a small subset of the available language IDs. Using an unordered_map allows only the reference languages to have space allocated.
This avoids manual new/delete of array.
english (au): 2 changes by krysclarke
chinese (simplified): 2 changes by WenSimEHRP
urdu: 6 changes by haidermazhar
russian: 2 changes by Ln-Wolf
catalan: 3 changes by J0anJosep
latvian: 2 changes by lexuslatvia
portuguese (brazilian): 2 changes by pasantoro
Fallback font searcher looked for the substituted ? glyph, which was removed by #12736.
Instead of comparing against a sprite, test against the font returning a missing glyph.
This should also improve performance of fallback font searching, as previously glyphs were actually rendered while searching.
english (au): 1 change by krysclarke
chinese (simplified): 1 change by WenSimEHRP
russian: 1 change by Ln-Wolf
slovak: 20 changes by Kukoluk
latvian: 1 change by lexuslatvia
portuguese: 1 change by azulcosta
portuguese (brazilian): 1 change by pasantoro
Initial colour is now always TC_INVALID, which is substituted with the desired colour when drawing the layout line.
This allows strings which differ only by initial colour to use the same layout cache entry, increasing the efficacy of the cache.
swedish: 9 changes by joeax910
english (us): 2 changes by 2TallTyler
luxembourgish: 4 changes by phreeze83
catalan: 2 changes by J0anJosep
latvian: 27 changes by lexuslatvia
* Fix: Allow changing size of default OpenTTD font.
Size configuration for default font was ignored as a different code path to load the font was followed.
Resolved by removing this additional path and conditionally selecting the default font.
This allows waypoints to be split into categories just like stations, instead of all being lumped together.
Station class labels with the first byte set to 0xFF will be treated in the same way as the 'WAYP' class.
english (au): 2 changes by krysclarke
chinese (simplified): 7 changes by WenSimEHRP
korean: 4 changes by telk5093
russian: 2 changes by Ln-Wolf
finnish: 2 changes by hpiirai
portuguese (brazilian): 2 changes by pasantoro
Temporary buffer for rendering glyphs was not freed after use. Instead let CGBitmapContextCreate() handle the buffer.
> data may be a pointer to pixels. If you pass NULL, the context will create its own buffer and free that buffer itself later. If you pass your own buffer, the context will not free it; it remains your buffer that you must free after you release the context, hopefully for the last time.
vietnamese: 13 changes by KhoiCanDev
chinese (simplified): 1 change by WenSimEHRP
finnish: 11 changes by hpiirai
french: 29 changes by ottdfevr
polish: 1 change by aefoes
Always treat empty groups as non-equal. Given that the case of both being empty is handled earlier, they cannot both be equal and empty.
Additionally if a loaded or loading set are all the same, only add one reference.
english (au): 11 changes by krysclarke
swedish: 7 changes by joeax910
english (us): 11 changes by 2TallTyler
chinese (simplified): 11 changes by WenSimEHRP
russian: 11 changes by Ln-Wolf
catalan: 11 changes by J0anJosep
portuguese: 13 changes by azulcosta
portuguese (brazilian): 11 changes by pasantoro
House picker is accessed from the Landscaping toolbar as there is no town toolbar.
Once placed these houses behave like any other and can be removed by players and towns.
Uses the unified picker system, so also supports used/saved favourites. As town building don't have class labels, town zones are use to imitate them.
When first opening the picker window, we attempt to find a valid class and type to select. If the picker window was closed with filters enabled, there may not be anything list that is usable.
Resolve this by using callbacks to find the first usable type when no types are listed.
english (au): 16 changes by krysclarke
chinese (simplified): 16 changes by XiaoJi-Game
korean: 19 changes by telk5093
russian: 1 change by Ln-Wolf
finnish: 16 changes by hpiirai
lithuanian: 1 change by khamper
portuguese: 17 changes by azulcosta
portuguese (brazilian): 16 changes by pasantoro
This allows ctrl-click on a type in a build-picker window to remember it
as a favourite. An new filter button to show only favourites makes it
simpler to use these types.
Favourite types are saved locally in favs.cfg, so are remembered between
games.
This filters the build-picker type lists to only show types that have
already been placed in the current game, making it simpler to get to
build matching features.
Toggling the "All" filter causes the class selection to be ignored, so
that items from all classes can be displayed together. The class text
filter is still applied.
This makes it easier to search amongst types for a feature.
These windows now share a common code base for choosing and display class and types.
An additional text filter is added to search types by name instead of just classes.
Standardises how the class index is stored in the spec, instead of relying ot the Spec structs having the same members.
This allows retrieving class_index and index without searching or using pointer arithmetic.
'cls_id' is renamed to 'class_index' to make it clearer that it is an index rather than the multichar label of the class.
There is a nice feature that synchronises the client settings upon setting up the company. Before
this, those commands would not be executed when no-actions-while-paused is set. This means that,
silently and depending on the server configuration, your wished for configuration might not be
there.
Similarly there is the president's face that's being set while creating a new company and setting
of the president/company name upon creation, when no-actions-while-paused is set.
So, just allow these operations also while paused to get a uniform experience when joining. To
keep the UI somewhat consistent, apply this "freedom" also to the other bits set from the company
UI; specifically company name and company colour.
english (au): 1 change by krysclarke
estonian: 25 changes by siimsoni
korean: 3 changes by telk5093
russian: 1 change by Ln-Wolf
finnish: 1 change by hpiirai
catalan: 5 changes by J0anJosep
latvian: 30 changes by lexuslatvia
lithuanian: 140 changes by khamper
portuguese: 1 change by azulcosta
portuguese (brazilian): 3 changes by pasantoro
english (au): 2 changes by krysclarke
english (us): 2 changes by 2TallTyler
greek: 4 changes by gh658804
russian: 2 changes by Ln-Wolf
finnish: 4 changes by hpiirai
danish: 2 changes by bscargo
lithuanian: 170 changes by khamper
french: 1 change by ben20471
portuguese: 2 changes by azulcosta
portuguese (brazilian): 2 changes by pasantoro
polish: 2 changes by pAter-exe
swedish: 2 changes by sereneavatar
norwegian (bokmal): 2 changes by eriksorngard
welsh: 19 changes by Ansbaradigeidfran
english (us): 2 changes by 2TallTyler
czech: 1 change by JsSusenka
lithuanian: 97 changes by khamper
french: 2 changes by Lishouuu
portuguese (brazilian): 1 change by pasantoro
polish: 2 changes by pAter-exe
english (au): 2 changes by krysclarke
korean: 2 changes by telk5093
russian: 2 changes by Ln-Wolf
finnish: 2 changes by hpiirai
danish: 2 changes by bscargo
lithuanian: 4 changes by dziugas1959
portuguese: 2 changes by azulcosta
portuguese (brazilian): 4 changes by pasantoro
Array/FixedSizeArray is actually a resizeable container that allocates space in chunks and allows resizing without invalidating pointers.
This is also a behaviour of std::deque, so use that instead.
This 'nice' structure was left around from #8258 just in case it might be used again.
Spoiler alert: it hasn't.
This removes manual memory management. And otherwise unused and untested code.
Slider widgets can only use a predefined list of values and strings to draw labels. This makes it difficult to vary the display by context.
Instead of providing a predefined list as a std::map, use a callback function instead. This function can decide what text to display, and can call SetDParam to dynamically set up strings.
Simplify AirportSpec data by storing layout information together in a vector, instead of separate arrays.
This removes manual memory management and separate count members.
The default layouts will be copied instead of always referring to the originals.
Use a vector to store the list of random sounds played for an industry.
The removes manual memory allocation, flags to control memory management, a separate count member, and a try/catch block.
chinese (simplified): 1 change by WenSimEHRP
greek: 52 changes by KyriakosMich
german: 3 changes by Wuzzy2
basque: 36 changes by Porrumentzio
danish: 3 changes by bscargo
Deferred window resize was being applied to the initial window resize event, resulting in some window state (e.g. scroll bar capacity) not being initialised when expected.
A comment about "will actually do nothing" is out of date as that is not the case with std::vector.
These lists are always short lived (either within a command handler or in a window) so don't shrink_to_fit.
After sorting and filter lists for GUI, we often shirnk them to reduce size. However this has very little benefit:
1) The memory has already been allocated, so it doesn't prevent that memory being required.
2) It causes a new allocation and copy when the vector is shrunk, actually using more memory.
3) The list is in window state, so the lifetime is only while the window is open.
4) When a filter is clearer, the original size will be needed again, which will cause another allocation.
In fact it is beneficial to reserve to the known maximum in most cases, so do that instead.
english (au): 3 changes by krysclarke
russian: 3 changes by Ln-Wolf
finnish: 6 changes by hpiirai
dutch: 6 changes by Afoklala
portuguese (brazilian): 4 changes by pasantoro
polish: 3 changes by pAter-exe
swedish: 7 changes by joeax910
vietnamese: 15 changes by anmatngu
greek: 31 changes by gh658804, 2 changes by KyriakosMich
hungarian: 2 changes by egri-nagy
portuguese (brazilian): 2 changes by pasantoro
GUIList has a pointer only to the start of each sort/filter func list, which has the potential for UB as it is unable to validate that the selected sort or filter type is in range.
Use a std::span instead and check if the selected type is in range before using it.
ExtractString does not need to find a string terminator as StrMakeValid already does this, so simply pass the full bounds of the buffer.
Removes lengthof, array indices, and needs only the buffer as a parameter.
SlCalcConvMemLen(), SlCalcConfFileLen() and CalcOldVarLen() follow a pattern of looking up part of a value in an array.
These function returns the size of bytes of a variable type, but is not very clear. Replace with a switch block instead.
Removes lengthof, array indices, and magic numbers.
Combine 3 separate arrays into a single struct. This keeps related data together, and avoids needing to check that each array is same length.
Use of constexpr construct ensures data in the array is not default-initialised.
Removes lengthof.
Combine two separate fixed length arrays to allow simpler iteration.
No need to check that arrays are all the same length.
No need to separately store the number of sprites to draw.
Removes the upper limit of the number of sprites that can be drawn.
Removes lengthof and array indices.
english (au): 3 changes by krysclarke
english (us): 3 changes by 2TallTyler
greek: 3 changes by gh658804
russian: 3 changes by Ln-Wolf
finnish: 5 changes by hpiirai
turkish: 7 changes by BeratSJ
portuguese: 3 changes by azulcosta
portuguese (brazilian): 3 changes by pasantoro
Default cargo label was not cleared (set to CT_INVALID) when using older 3-slot acceptance properties for house and industry tiles.
Missed in #12053 and #12062.
The BaseSet type is not needed after the window is constructed, only the filename and name are required, which can be passed as parameters from `ShowBaseSetTextfileWindow()` instead.
This avoids compiling three instances of `BaseSetTextfileWindow`.
Conversion to set default group livery is in the wrong place (not in `AfterLoadGame()`), however it is not necessary any more as `AfterLoadGame()` always calls the function `UpdateCompanyLiveries()` which will do the same thing.
Industry accepted/produced was trimmed too early for original and pre-SLV_78 saves, as cargo type was not stored per slot so all slots look invalid to the trim function.
Using Action A above the baseset is error prone as the sprites are not fixed and can be moved around.
Any NewGRF doing so is likely to break in the future, so force it to break instead.
* Codechange: Replace C-style casts to size_t with static_cast.
This touches only simple value-type casts.
* Codechange: Replace static_cast<size_t>(-1) with SIZE_MAX
Co-authored-by: Rubidium <rubidium@openttd.org>
When resolving NewGRF, the parent town_scope is lazily initialised as it does not always need to be used.
Replace the manually managed pointer with std::optional to simplify. Using std::optional avoids extra memory allocation.
english (au): 4 changes by krysclarke
russian: 4 changes by Ln-Wolf
finnish: 7 changes by hpiirai
portuguese: 4 changes by azulcosta
portuguese (brazilian): 5 changes by pasantoro
polish: 4 changes by pAter-exe
The class limit is arbitrary and not stored in game state.
This change prevents all entities in classes after the 255th class from being dumped into the first class.
english (au): 5 changes by krysclarke
chinese (simplified): 1 change by WenSimEHRP
catalan: 7 changes by J0anJosep
portuguese (brazilian): 27 changes by pasantoro
greek: 5 changes by gh658804
finnish: 7 changes by hpiirai
ukrainian: 56 changes by Quantom2, 14 changes by imlystyi
latvian: 14 changes by lexuslatvia
portuguese: 14 changes by azulcosta
portuguese (brazilian): 10 changes by pasantoro
polish: 5 changes by pAter-exe
Sprite IDs are not useful information given they change don't refer to anything outside the loaded game.
Instead, include the filename and nfo line at minimum, and include action A or action 5 sprite replacement information if applicable.
If the small font is set to a larger size than the normal font for some reason, viewport signs would be drawn incorrect as the area marked dirty only considered the normal size font.
swedish: 6 changes by joeax910
norwegian (bokmal): 2 changes by eriksorngard
chinese (simplified): 2 changes by WenSimEHRP
dutch: 2 changes by Afoklala
Aircraft can float above the ground when crashed as the counter limit to reach the ground is too low.
Instead reset the counter until the aircraft reaches the ground, then continue the timer.
english (us): 2 changes by 2TallTyler
finnish: 2 changes by hpiirai
ukrainian: 2 changes by Quantom2
danish: 2 changes by beruic
portuguese (brazilian): 22 changes by pasantoro
english (au): 2 changes by krysclarke
swedish: 2 changes by joeax910
greek: 2 changes by gh658804
russian: 3 changes by its5Q
catalan: 2 changes by J0anJosep
spanish: 2 changes by MontyMontana
portuguese: 2 changes by azulcosta
portuguese (brazilian): 27 changes by pasantoro
polish: 2 changes by pAter-exe
Now that the default font =/= sprite font, there is a different way to invoke the sprite font, and default size applies to default (not sprite).
Also, interface scaling now affects the font size.
english (au): 1 change by krysclarke
norwegian (bokmal): 1 change by eriksorngard
spanish (mexican): 32 changes by rgonzalez-py
english (us): 3 changes by 2TallTyler
russian: 3 changes by Ln-Wolf
ukrainian: 18 changes by StepanIvasyn
lithuanian: 6 changes by dziugas1959
portuguese (brazilian): 11 changes by pasantoro
The server sends shutdown and newgame (reboot) packets to any connected client.
This can be useful, so you can tell clients that are trying to join that the
server is restarting. However, that means that packets can be sent before a
version check has been done.
So, these packets should be in the stable packet range instead of the one that
is unstable and guarded by a version check.
english (au): 2 changes by krysclarke
vietnamese: 1 change by KhoiCanDev
chinese (simplified): 9 changes by WenSimEHRP
greek: 152 changes by gh658804
russian: 3 changes by Ln-Wolf
finnish: 2 changes by hpiirai
ukrainian: 9 changes by StepanIvasyn
danish: 2 changes by bscargo
portuguese: 5 changes by azulcosta
portuguese (brazilian): 35 changes by pasantoro
vietnamese: 1 change by KhoiCanDev
chinese (simplified): 1 change by WenSimEHRP
ukrainian: 11 changes by StepanIvasyn
catalan: 1 change by J0anJosep
danish: 1 change by bscargo
dutch: 3 changes by Afoklala
portuguese (brazilian): 58 changes by pasantoro
When hovering a tile containing a station, show existing coverage for
that station even when adjacent to a different station.
Co-authored-by: Peter Nelson <peter@fuzzle.org>
english (au): 1 change by krysclarke
norwegian (bokmal): 1 change by eriksorngard
english (us): 1 change by 2TallTyler
korean: 3 changes by telk5093
german: 1 change by Wuzzy2
finnish: 3 changes by hpiirai
ukrainian: 12 changes by StepanIvasyn
portuguese (brazilian): 81 changes by pasantoro
polish: 1 change by pAter-exe
english (us): 2 changes by 2TallTyler
vietnamese: 2 changes by KhoiCanDev
german: 2 changes by Wuzzy2
ukrainian: 2 changes by StepanIvasyn
portuguese (brazilian): 9 changes by pasantoro
english (au): 2 changes by krysclarke
norwegian (bokmal): 2 changes by eriksorngard
chinese (simplified): 31 changes by lysinelai
greek: 7 changes by Xertoveizer
ukrainian: 14 changes by StepanIvasyn
danish: 2 changes by bscargo
lithuanian: 15 changes by dziugas1959
spanish: 2 changes by MontyMontana
french: 2 changes by glx22
portuguese (brazilian): 52 changes by pasantoro
polish: 2 changes by pAter-exe
Replace both group list implementations (vehicle group list and company colour group list) with a single implementation, using a struct to hold the group and indentation level instead of two separate lists. Parts that were previously duplicated are now shared.
This simplifies the handling of variables.
`ChooseShipTrack` is called upon entering `tile`, and looking further back to the caller, it can be deduced that `v->tile` matches `src_tile`. With that said, `enterdir` can also be removed, as it's not used anywhere else.
`CreateRandomPath` and `GetRandomFollowUpTrackdir` is being fed `src_tile` as it's 2nd parameter. This could be eliminated, as `v` is also being passed to it. Just use `v->tile` in those functions.
norwegian (bokmal): 11 changes by eriksorngard
chinese (simplified): 1 change by WenSimEHRP
finnish: 23 changes by hpiirai
ukrainian: 21 changes by StepanIvasyn
danish: 32 changes by bscargo
spanish: 6 changes by MontyMontana
portuguese (brazilian): 50 changes by pasantoro
english (au): 45 changes by krysclarke
norwegian (bokmal): 256 changes by eriksorngard
welsh: 41 changes by Ansbaradigeidfran
english (us): 45 changes by 2TallTyler
russian: 11 changes by Ln-Wolf
finnish: 18 changes by hpiirai
ukrainian: 20 changes by StepanIvasyn
catalan: 167 changes by J0anJosep
danish: 11 changes by bscargo
spanish: 35 changes by lrlopez
french: 41 changes by ottdfevr
portuguese: 44 changes by jcteotonio
portuguese (brazilian): 168 changes by pasantoro
Adds missing characters for Chuvash and Serbian translations. Adds support for combining diacritics (needed for for Cyrillic es with accent) and corrects miscoded Cyrillic es with descender.
This mainly as they are not expected to fail, or give more information
than the other targets already would. And this is just hogging up
the CI pipeline. On average, these targets take ~80 CPU-minutes to
finish.
Autobuild also fetches dependencies and other things, while those
are already ready on the system. This seems to cost ~1 minutes,
for no actual good reason.
swedish: 7 changes by joeax910
norwegian (bokmal): 242 changes by eriksorngard
welsh: 609 changes by Ansbaradigeidfran
english (us): 3 changes by 2TallTyler
chinese (simplified): 1 change by WenSimEHRP
ukrainian: 21 changes by StepanIvasyn
latvian: 1 change by lexuslatvia
dutch: 1 change by Jaws3rd
esperanto: 53 changes by legoscia
portuguese (brazilian): 19 changes by pasantoro
An off-by-one in EnsureVisibleCaption causes the minimum visible caption height to be 13 scaled pixels and 1 unscaled pixel. At 1x interface scale, this 'happens' to be the complete height of a caption, but at other interface scales it is not.
Instead of using a scaled fixed value, correct the off-by-one and just use the window's actual caption height instead.
english (au): 1 change by krysclarke
norwegian (bokmal): 545 changes by eriksorngard
chinese (traditional): 75 changes by wpi3
galician: 24 changes by pvillaverde
chinese (simplified): 1 change by WenSimEHRP
russian: 1 change by Ln-Wolf
finnish: 4 changes by hpiirai
ukrainian: 16 changes by StepanIvasyn
catalan: 1 change by J0anJosep
danish: 1 change by bscargo
french: 3 changes by ottdfevr
portuguese: 1 change by azulcosta
esperanto: 203 changes by legoscia
portuguese (brazilian): 21 changes by pasantoro
polish: 1 change by pAter-exe
From macos-14, vcpkg is no longer installed on the runner-image.
It stands to reason that this will also roll out to new images
for other OSes. To be pre-emptive about it, start using our own
cloned vcpkg for all targets.
Normally "cargo install" will use the latest dependencies, but
this causes an issue with "dump_syms". Use "--locked" makes sure
we use the dependency versions as indicated by "dump_syms", instead
of the latest version.
chinese (simplified): 27 changes by WenSimEHRP
korean: 2 changes by telk5093
greek: 42 changes by Xertoveizer
indonesian: 32 changes by tsaqibfs
slovak: 184 changes by ApplePie420
danish: 2 changes by bscargo
latvian: 2 changes by lexuslatvia
dutch: 2 changes by Afoklala
portuguese: 16 changes by jcteotonio
portuguese (brazilian): 77 changes by pasantoro
chinese (simplified): 2 changes by WenSimEHRP
luxembourgish: 2 changes by phreeze83
hungarian: 2 changes by PstasDev
german: 2 changes by Wuzzy2
ukrainian: 10 changes by StepanIvasyn
slovak: 197 changes by ApplePie420
catalan: 2 changes by J0anJosep
portuguese (brazilian): 35 changes by pasantoro
english (au): 2 changes by krysclarke
vietnamese: 1 change by KhoiCanDev
estonian: 4 changes by RM87
russian: 8 changes by Ln-Wolf
ukrainian: 27 changes by StepanIvasyn
slovak: 34 changes by palsoft333
tamil: 41 changes by Aswn
spanish: 4 changes by MontyMontana
portuguese (brazilian): 72 changes by pasantoro
polish: 3 changes by pAter-exe
Avoid iterating all towns and industries when updating station catchment, and scan a limited portion of the map instead.
This provides a modest performance benefit when many towns/industries exist.
chinese (simplified): 2 changes by WenSimEHRP
russian: 1 change by Ln-Wolf
ukrainian: 9 changes by StepanIvasyn
portuguese (brazilian): 66 changes by pasantoro
chinese (simplified): 6 changes by WenSimEHRP
serbian: 16 changes by nkrs
ukrainian: 1 change by StepanIvasyn
portuguese (brazilian): 234 changes by pasantoro
estonian: 166 changes by siimsoni, 22 changes by RM87
chinese (simplified): 6 changes by WenSimEHRP
serbian: 172 changes by nkrs
ukrainian: 11 changes by StepanIvasyn
spanish: 1 change by MontyMontana
portuguese (brazilian): 149 changes by pasantoro
When using the sprite picker the screen is redrawn so that the sprites under the mouse cursor can be captured. This redraw also caused the sprite aligner window to be redrawn before the OnInvalidateData event that updates its scrollbars with the list count.
chinese (simplified): 26 changes by WenSimEHRP
korean: 5 changes by telk5093
dutch: 9 changes by Afoklala
portuguese (brazilian): 25 changes by pasantoro
hungarian: 96 changes by titanicbobo, 11 changes by pnpBrumi
ukrainian: 19 changes by StepanIvasyn
latvian: 1 change by lexuslatvia
spanish: 9 changes by MontyMontana
portuguese (brazilian): 94 changes by pasantoro
english (us): 9 changes by 2TallTyler
chinese (simplified): 10 changes by WenSimEHRP
luxembourgish: 21 changes by phreeze83
greek: 11 changes by Xertoveizer
hungarian: 60 changes by titanicbobo
german: 37 changes by frosch123
french: 9 changes by Bulest
portuguese (brazilian): 74 changes by pasantoro
polish: 5 changes by pAter-exe
english (au): 1 change by krysclarke
swedish: 1 change by niklasva
chinese (simplified): 6 changes by WenSimEHRP
korean: 21 changes by telk5093
hungarian: 1 change by PstasDev
italian: 1 change by Rivarossi
belarusian: 7 changes by KorneySan
russian: 7 changes by Ln-Wolf, 3 changes by KorneySan
catalan: 9 changes by J0anJosep
danish: 7 changes by bscargo
french: 7 changes by ottdfevr
portuguese: 1 change by jcteotonio
hindi: 2 changes by michaelsmassey
portuguese (brazilian): 115 changes by pasantoro
polish: 1 change by pAter-exe
Remap sprites start with a count byte followed by 256 entries, but
SetupColoursAndInitialWindow did not take account of this extra byte and
therefore started at palette index 0xC5 instead of 0xC6. This caused the
first colour of each gradient to be incorrect and all shades were actually
1 step lower in the gradient than indicated.
Some windows resize themselves during painting and issue ReInit(). In this case deferred OnResize() causes a visible glitch as the event is handled on the next redraw.
english (au): 6 changes by krysclarke
swedish: 19 changes by sereneavatar
estonian: 30 changes by RM87
chinese (simplified): 3 changes by Kevin-mao0721
hungarian: 60 changes by titanicbobo
italian: 6 changes by Rivarossi
russian: 3 changes by Ln-Wolf, 3 changes by KorneySan
finnish: 6 changes by hpiirai
ukrainian: 7 changes by StepanIvasyn
latvian: 6 changes by lexuslatvia
portuguese: 37 changes by azulcosta
portuguese (brazilian): 19 changes by pasantoro
polish: 6 changes by SzyZuu
vietnamese: 3 changes by KhoiCanDev
chinese (simplified): 5 changes by WenSimEHRP
hungarian: 63 changes by titanicbobo
belarusian: 47 changes by KorneySan
finnish: 2 changes by hpiirai
ukrainian: 25 changes by StepanIvasyn
danish: 38 changes by bscargo
portuguese (brazilian): 158 changes by pasantoro
english (au): 2 changes by krysclarke
spanish (mexican): 149 changes by Can202
estonian: 11 changes by RM87
chinese (simplified): 18 changes by WenSimEHRP
hungarian: 2 changes by PstasDev
italian: 195 changes by Rivarossi
serbian: 42 changes by nkrs
german: 2 changes by Wuzzy2
belarusian: 537 changes by KorneySan
russian: 25 changes by KorneySan
ukrainian: 21 changes by StepanIvasyn
turkish: 14 changes by jnmbk
latvian: 2 changes by lexuslatvia
dutch: 1 change by iamthedutchdude
spanish: 15 changes by MontyMontana
french: 2 changes by ottdfevr
portuguese: 2 changes by jcteotonio, 2 changes by azulcosta
portuguese (brazilian): 149 changes by pasantoro
polish: 2 changes by pAter-exe
english (us): 24 changes by 2TallTyler
vietnamese: 13 changes by KhoiCanDev
estonian: 7 changes by RM87
german: 16 changes by Wuzzy2
belarusian: 328 changes by KorneySan
russian: 6 changes by KorneySan, 5 changes by Ln-Wolf
ukrainian: 9 changes by StepanIvasyn
catalan: 18 changes by J0anJosep
danish: 61 changes by bscargo
french: 8 changes by ottdfevr
portuguese: 29 changes by jcteotonio, 12 changes by azulcosta
portuguese (brazilian): 185 changes by pasantoro
polish: 1 change by pAter-exe
english (au): 12 changes by krysclarke
chinese (simplified): 84 changes by WenSimEHRP
russian: 13 changes by Ln-Wolf
finnish: 12 changes by hpiirai
ukrainian: 12 changes by StepanIvasyn
latvian: 19 changes by lexuslatvia
french: 1 change by ZarTek-Creole
portuguese (brazilian): 169 changes by pasantoro
polish: 12 changes by pAter-exe
# Our GUI code tends to use switches for OnClick handlers, DrawWidget, and UpdateWidgetSize. Sometimes GUIs just don't have many elements, but we want to keep consistency.
@@ -10,6 +10,8 @@ What is simple to some might appear very complicated to others. Documentation he
* Function names use [CamelCase](http://www.wikipedia.org/wiki/Camelcase) without underscores.
* Opening curly bracket **{** for a function starts on the next line.
* 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.
```c++
void ThisIsAFunction()
{
@@ -157,7 +159,7 @@ enum SomeEnumeration {
* Use curly braces and put the contained statements on their own lines (e.g., don't put them directly after the **if**).
* Opening curly bracket **{** stays on the first line, closing curly bracket **}** gets a line to itself (except for the **}** preceding an **else**, which should be on the same line as the **else**).
* When only a single statement is contained, the brackets can be omitted. In this case, put the single statement on the same line as the preceding keyword (**if**, **while**, etc.). Note that this is only allowed for if statements without an **else** clause.
* All fall throughs must be documented, using a **FALLTHROUGH** define/macro.
* Non-trivial fall throughs must be documented, using a `[[fallthrough]]` attribute.
* The NOT_REACHED() macro can be used in default constructs that should never be reached.
* Unconditional loops are written with **`for (;;) {`**
@@ -180,7 +182,7 @@ switch (a) {
case 1:
DoSomething();
FALLTHROUGH;
[[fallthrough]];
case 2:
DoMore();
@@ -191,7 +193,7 @@ switch (a) {
int r = 2;
DoEvenMore(a);
FALLTHROUGH;
[[fallthrough]];
}
case 4: {
@@ -248,17 +250,50 @@ Templates are a very powerful C++ tool, but they can easily confuse beginners. T
* Templates are to be documented in a very clear and verbose manner. Never assume anything in the documentation.
* the template keyword and the template layout get a separate line. typenames are either "T" or preceded by a "T", integers get a single capital letter or a descriptive name preceded by "T".
```c++
template <typename T, typename Tsomething, int N, byte Tnumber_of_something>
template <typename T, typename Tsomething, int N, uint8_t Tnumber_of_something>
int Func();
```
* If you are writing one or more template class in the dedicated header file, use file.hpp for its name instead of file.h. This will let others know that it is template library (includes also implementation), not just header with declarations.
### Code Comment Vertical Alignment
When adding code or comments to an existing formatted section, follow the existing style if possible without editing the preexisting lines.
If your addition cannot be aligned with existing code, do not align the comments with anything and use only a single space between the code and the comment.
Good:
```c++
enum Vehicle {
BUS, ///< Take the bus.
+ CAR, ///< Drive your car.
BIKE, ///< Ride your bike
+ TRAIN, ///< Catch the train.
}
```
"Car" is shorter than Bike which allows you to easily align the new comment. "Train" is longer. It is *NOT* desirable to change the vertical comment alignment of this enum.
Bad:
```c++
enum Vehicle {
- BUS, ///< Take the bus.
- BIKE, ///< Ride your bike
+ BUS, ///< Take the bus.
+ CAR, ///< Drive your car.
+ BIKE, ///< Ride your bike
+ TRAIN, ///< Catch the train.
}
```
OpenTTD used to vertically-align inline Doxygen comments as shown above. OpenTTD has since stopped strictly following this rule to keep diffs smaller and reduce pollution to the git blame history for non-functional changes.
### Other important rules
* Put a space before and after binary operators: "a + b", "a == b", "a & b", "a <<= b", etc.. Exceptions are ".", "->" and "[]" (no spaces) and "," (just space after it).
* Put parenthesis where it improves readability: "*(b++)" instead of "*b++", and "if ((a & b) && c == 2)" instead of "if (a & b && c == 2)".
* Do not put external declarations in implementation (i.e. cpp) files.
* Use const where possible.
* Do not typedef enums and structs.
* Don't treat non-flags as flags: use "if (char_pointer != nullptr && *char_pointer != '\0')", not "if (char_pointer && *char_pointer)".
* Use "free(p)" instead of "if (p != nullptr) free(p)". "free(nullptr)" doesn't hurt anyone.
@@ -448,7 +483,7 @@ Do not mention two keywords; if two apply, pick one that best represents the com
The `<details>` part starts with a capital and does not end with a dot.
Try to be descriptive to what the player will notice, not to what is actually being changed in the code.
See `changelog.txt` for inspiration.
See `changelog.md` for inspiration.
To further structure the changelog, you can add components. Example are:
@@ -29,7 +29,7 @@ open most older savegames or use the content downloading system.
## Windows
You need Microsoft Visual Studio 2017 or more recent.
You need Microsoft Visual Studio 2022 or more recent.
You can download the free Visual Studio Community Edition from Microsoft at
https://visualstudio.microsoft.com/vs/community/.
@@ -65,7 +65,7 @@ To install both the x64 (64bit) and x86 (32bit) variants (though only one is nec
You can open the folder (as a CMake project). CMake will be detected, and you can compile from there.
If libraries are installed but not found, you need to set VCPKG_TARGET_TRIPLET in CMake parameters.
For Visual Studio 2017 you also need to set CMAKE_TOOLCHAIN_FILE.
For Visual Studio 2022 you also need to set CMAKE_TOOLCHAIN_FILE.
(Typical values are shown in the MSVC project file command line example)
Alternatively, you can create a MSVC project file via CMake. For this
@@ -75,7 +75,7 @@ that comes with vcpkg. After that, you can run something similar to this:
```powershell
mkdirbuild
cd build
cmake.exe..-G"Visual Studio 16 2019"-DCMAKE_TOOLCHAIN_FILE="<location of vcpkg>\vcpkg\scripts\buildsystems\vcpkg.cmake"-DVCPKG_TARGET_TRIPLET="x64-windows-static"
cmake.exe..-G"Visual Studio 17 2022"-DCMAKE_TOOLCHAIN_FILE="<location of vcpkg>\vcpkg\scripts\buildsystems\vcpkg.cmake"-DVCPKG_TARGET_TRIPLET="x64-windows-static"
```
Change `<location of vcpkg>` to where you have installed vcpkg. After this
@@ -83,7 +83,7 @@ in the build folder are MSVC project files. MSVC can rebuild the project
files himself via the `ZERO_CHECK` project.
## All other platforms
Minimum required version of CMake is 3.9.
Minimum required version of CMake is 3.16.
By default this produces a Debug build with assertations enabled.
This is a far slower build than release builds.
@@ -115,9 +115,9 @@ builds.
## Supported compilers
Every compiler that is supported by CMake and supports C++17, should be
Every compiler that is supported by CMake and supports C++20, should be
able to compile OpenTTD. As the exact list of compilers changes constantly,
we refer to the compiler manual to see if it supports C++17, and to CMake
we refer to the compiler manual to see if it supports C++20, and to CMake
You may also want the guide to [compiling OpenTTD](./COMPILING.md).
## Use of AI
OpenTTD is a labour of love, created by people.
Please refrain from submitting issues or pull requests that have been generated by an LLM or other fully-automated tools.
Any submission that is in violation of this policy will be closed, and the submitter may be blocked from this repository without warning.
If you submit an issue, you need to understand what your issue description is saying.
You need to be able to answer questions about your bug report or feature request.
Using an AI tool to _proofread_ your issue/comment text is acceptable. Using an AI tool to _write_ your issue/comment text is not.
If you submit a pull request, you need to understand what every line of code you've changed does.
If you can't explain why your PR is doing something, then do not submit it.
Using an AI tool to generate entire lines of code is unacceptable.
The rationale behind this policy is that automated contributions are a waste of the maintainers' time.
Humans spend their time and brainpower reviewing every submission.
Issues or pull requests generated by automation tools create an imbalance of effort between the submitter and the reviewer.
Nobody learns anything when a maintainer reviews code written by an LLM.
Additionally, AI-generated code conflicts with this project's license (GPL v2), since you cannot truly release code for use if you didn't author it yourself.
# 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 <http://www.gnu.org/licenses/>.
# 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>.
@@ -37,12 +37,10 @@ Both 'stable' and 'nightly' versions are available for download:
OpenTTD is also available for free on [Steam](https://store.steampowered.com/app/1536610/OpenTTD/), [GOG.com](https://www.gog.com/game/openttd), and the [Microsoft Store](https://www.microsoft.com/p/openttd-official/9ncjg5rvrr1c). On some platforms OpenTTD will be available via your OS package manager or a similar service.
## 1.2) OpenTTD gameplay manual
OpenTTD has a [community-maintained wiki](https://wiki.openttd.org/), including a gameplay manual and tips.
## 1.3) Supported platforms
OpenTTD has been ported to several platforms and operating systems.
@@ -56,6 +54,7 @@ The currently supported platforms are:
Other platforms may also work (in particular various BSD systems), but we don't actively test or maintain these.
### 1.3.1) Legacy support
Platforms, languages and compilers change.
We'll keep support going on old platforms as long as someone is interested in supporting them, except where it means the project can't move forward to keep up with language and compiler features.
@@ -72,7 +71,6 @@ For some platforms these will be downloaded during the installation process if r
For some platforms, you will need to refer to [the installation guide](https://wiki.openttd.org/en/Manual/Installation).
### 1.4.1) Free graphics and sound files
The free data files, split into OpenGFX for graphics, OpenSFX for sounds and
@@ -85,7 +83,6 @@ OpenMSX for music can be found at:
Please follow the readme of these packages about the installation procedure.
The Windows installer can optionally download and install these packages.
### 1.4.2) Original Transport Tycoon Deluxe graphics and sound files
If you want to play with the original Transport Tycoon Deluxe data files you have to copy the data files from the CD-ROM into the baseset/ directory.
@@ -100,7 +97,6 @@ You need to copy the following files:
- trgir.grf or TRGI.GRF
- trgtr.grf or TRGT.GRF
### 1.4.3) Original Transport Tycoon Deluxe music
If you want the Transport Tycoon Deluxe music, copy the appropriate files from the original game into the baseset folder.
@@ -108,7 +104,6 @@ If you want the Transport Tycoon Deluxe music, copy the appropriate files from t
- TTD for DOS: The GM.CAT file
- Transport Tycoon Original: The GM.CAT file, but rename it to GM-TTO.CAT
## 1.5) Add-on content / mods
OpenTTD features multiple types of add-on content, which modify gameplay in different ways.
@@ -117,7 +112,6 @@ Most types of add-on content can be downloaded within OpenTTD via the 'Check Onl
Add-on content can also be installed manually, but that's more complicated; the [OpenTTD wiki](https://wiki.openttd.org/) may offer help with that, or the [OpenTTD directory structure guide](./docs/directory_structure.md).
### 1.5.1) Social Integration
OpenTTD has the ability to load plugins to integrate with Social Platforms like Steam, Discord, etc.
@@ -126,7 +120,6 @@ To enable such integration, the plugin for the specific platform has to be downl
See [OpenTTD's website](https://www.openttd.org), under Downloads, for what plugins are available.
### 1.6) OpenTTD directories
OpenTTD uses its own directory structure to store game data, add-on content etc.
@@ -137,7 +130,6 @@ For more information, see the [directory structure guide](./docs/directory_struc
If you want to compile OpenTTD from source, instructions can be found in [COMPILING.md](./COMPILING.md).
## 2.0) Contact and Community
'Official' channels
@@ -160,12 +152,10 @@ You can play OpenTTD with others, either cooperatively or competitively.
See the [multiplayer documentation](./docs/multiplayer.md) for more details.
### 2.2) Contributing to OpenTTD
We welcome contributors to OpenTTD. More information for contributors can be found in [CONTRIBUTING.md](./CONTRIBUTING.md)
### 2.3) Reporting bugs
Good bug reports are very helpful. We have a [guide to reporting bugs](./CONTRIBUTING.md#bug-reports) to help with this.
@@ -173,12 +163,10 @@ Good bug reports are very helpful. We have a [guide to reporting bugs](./CONTRI
Desyncs in multiplayer are complex to debug and report (some software development skils are required).
Instructions can be found in [debugging and reporting desyncs](./docs/debugging_desyncs.md).
### 2.4) Translating
OpenTTD is translated into many languages. Translations are added and updated via the [online translation tool](https://translator.openttd.org).
## 3.0) Licensing
OpenTTD is licensed under the GNU General Public License version 2.0.
@@ -212,6 +200,9 @@ See `src/3rdparty/monocypher/LICENSE.md` for the complete license text.
The OpenTTD Social Integration API in `src/3rdparty/openttd_social_integration_api` is licensed under the MIT license.
See `src/3rdparty/openttd_social_integration_api/LICENSE` for the complete license text.
## 4.0 Credits
The atomic datatype support detection in `cmake/3rdparty/llvm/CheckAtomic.cmake` is licensed under the Apache 2.0 license.
See `cmake/3rdparty/llvm/LICENSE.txt` for the complete license text.
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
AILog.Info("0.7 API compatibility in effect:");
/* This file contains code to downgrade the API from 1.0 to 0.7. */
AILog.Info(" - AITown::GetLastMonthProduction's behaviour has slightly changed.");
AILog.Info(" - AISubsidy::GetDestination returns STATION_INVALID for awarded subsidies.");
AILog.Info(" - AISubsidy::GetSource returns STATION_INVALID for awarded subsidies.");
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
AILog.Info("1.0 API compatibility in effect.");
/* This file contains code to downgrade the API from 1.1 to 1.0. */
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
AILog.Info("1.1 API compatibility in effect.");
/* This file contains code to downgrade the API from 1.2 to 1.1. */
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
AILog.Info("1.10 API compatibility in effect.");
/* 13 really checks RoadType against RoadType */
AIRoad._HasRoadType <- AIRoad.HasRoadType;
AIRoad.HasRoadType <- function(tile, road_type)
{
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
foreach (rt, _ in list) {
if (AIRoad._HasRoadType(tile, rt)) {
return true;
}
}
return false;
}
/* This file contains code to downgrade the API from 1.11 to 1.10. */
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
AILog.Info("1.11 API compatibility in effect.");
/* 13 really checks RoadType against RoadType */
AIRoad._HasRoadType <- AIRoad.HasRoadType;
AIRoad.HasRoadType <- function(tile, road_type)
{
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
foreach (rt, _ in list) {
if (AIRoad._HasRoadType(tile, rt)) {
return true;
}
}
return false;
}
/* This file contains code to downgrade the API from 12 to 1.11. */
* 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 <http://www.gnu.org/licenses/>.
* 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>.
* 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 <http://www.gnu.org/licenses/>.
* 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>.
* 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 <http://www.gnu.org/licenses/>.
* 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>.
* 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 <http://www.gnu.org/licenses/>.
* 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>.
* 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 <http://www.gnu.org/licenses/>.
* 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>.
* 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 <http://www.gnu.org/licenses/>.
* 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>.
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
AILog.Info("1.8 API compatibility in effect.");
/* This file contains code to downgrade the API from 1.9 to 1.8. */
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
AILog.Info("1.9 API compatibility in effect.");
/* 13 really checks RoadType against RoadType */
AIRoad._HasRoadType <- AIRoad.HasRoadType;
AIRoad.HasRoadType <- function(tile, road_type)
{
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
foreach (rt, _ in list) {
if (AIRoad._HasRoadType(tile, rt)) {
return true;
}
}
return false;
}
/* This file contains code to downgrade the API from 1.10 to 1.9. */
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
AILog.Info("12 API compatibility in effect.");
/* This file contains code to downgrade the API from 13 to 12. */
/* 13 really checks RoadType against RoadType */
AIRoad._HasRoadType <- AIRoad.HasRoadType;
AIRoad.HasRoadTypeCompat12 <- AIRoad.HasRoadType;
AIRoad.HasRoadType <- function(tile, road_type)
{
local list = AIRoadTypeList(AIRoad.GetRoadTramType(road_type));
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
AILog.Info("13 API compatibility in effect.");
/* This file contains code to downgrade the API from 14 to 13. */
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
/* This file contains code to downgrade the API from 15 to 14. */
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
GSLog.Info("1.10 API compatibility in effect.");
/* This file contains code to downgrade the API from 1.11 to 1.10. */
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
GSLog.Info("1.11 API compatibility in effect.");
/* This file contains code to downgrade the API from 12 to 1.11. */
/* 13 really checks RoadType against RoadType */
GSRoad._HasRoadType <- GSRoad.HasRoadType;
GSRoad.HasRoadType <- function(tile, road_type)
{
local list = GSRoadTypeList(GSRoad.GetRoadTramType(road_type));
* 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 <http://www.gnu.org/licenses/>.
* 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>.
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
GSLog.Info("1.3 API compatibility in effect.");
/* This file contains code to downgrade the API from 1.4 to 1.3. */
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
GSLog.Info("1.4 API compatibility in effect.");
/* This file contains code to downgrade the API from 1.5 to 1.4 */
/* 1.5 adds a game element reference to the news. */
* 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 <http://www.gnu.org/licenses/>.
* 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>.
* 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 <http://www.gnu.org/licenses/>.
* 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>.
* 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 <http://www.gnu.org/licenses/>.
* 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>.
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
GSLog.Info("1.8 API compatibility in effect.");
/* This file contains code to downgrade the API from 1.9 to 1.8. */
* 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 <http://www.gnu.org/licenses/>.
* 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>.
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
GSLog.Info("12 API compatibility in effect.");
/* This file contains code to downgrade the API from 13 to 12. */
/* 13 really checks RoadType against RoadType */
GSRoad._HasRoadType <- GSRoad.HasRoadType;
GSRoad.HasRoadTypeCompat12 <- GSRoad.HasRoadType;
GSRoad.HasRoadType <- function(tile, road_type)
{
local list = GSRoadTypeList(GSRoad.GetRoadTramType(road_type));
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
GSLog.Info("13 API compatibility in effect.");
/* This file contains code to downgrade the API from 14 to 13. */
* 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 <http://www.gnu.org/licenses/>.
* 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>.
*/
/* This file contains code to downgrade the API from 15 to 14. */
GSBridge.GetBridgeID <- GSBridge.GetBridgeType;
/* Emulate old GSText parameter padding behaviour */
GSText.SCRIPT_TEXT_MAX_PARAMETERS <- 20;
class GSCompat14 {
function Text(text)
{
if (typeof text == "string") return text;
if (typeof text == "instance" && text instanceof GSText) return text;
- a monospace font (used for text files such as NewGRF readmes).
You can use the following types of fonts with OpenTTD:
## OpenTTD's default fonts
These fonts are OpenTTD Sans (small and medium), OpenTTD Serif (large) and OpenTTD Mono (monospace). They are distributed as part of OpenTTD since version 14. The font files are included in the baseset directory of OpenTTD.
These fonts are active by default and support the Latin, Greek and Cyrillic scripts at present.
## Traditional sprite fonts
These are the classic bitmap fonts included as part of the base graphics. They support only the Latin script.
These fonts can be activated in the Graphics section of the Game options window, by enabling the option "Use traditional sprite fonts".
## System fonts
These are fonts installed on your computer. OpenTTD tries to automatically detect and activate a suitable system font in case you have selected a language not supported by the default fonts. However, if this fails, you may have to set a font manually.
There are two ways to manually set system fonts, using the `font` console command or editing the openttd.cfg file.
### Using the console
Open the console. On most keyboards, this is done by pressing the key to the left of 1 (\` on most English keyboards).
The command to change a font is `font [medium|small|large|mono] [<font name>] [<size>]`.
For example, `font large "Times New Roman" 16`.
The font name should be enclosed in double quotes if it contains spaces. Note that the size provided is multiplied by the interface scaling factor.
You can reset the font and size to the defaults by providing the font name "" (a blank font name). This will result in the OpenTTD default font or sprite font (depending on the setting) if you are using a supported language, or a default font determined by your OS otherwise.
You can view the current font configuration by running the command `font` without any arguments.
For more information, run the command `help font`.
### Using openttd.cfg
In openttd.cfg, the following settings under the `[misc]` section determine the font (this is just an example):
```
small_font =
medium_font = Arial Bold
large_font = Times New Roman
mono_font =
small_size = 6
medium_size = 10
large_size = 18
mono_size = 10
```
If these settings are not present, you can add them under the `[misc]` section.
If any font names are left blank, the default font and size are used.
If you cannot find the openttd.cfg file, see [the directory structure guide](./directory_structure.md).
To aid players in scenario creation, OpenTTD's Scenario Editor can import town data from external JSON files. This enables players to use an image editing program to align town coordinates with a real-world heightmap using a map underlay, instead of guessing at the correct locations in Scenario Editor itself.
This town data consists of a JSON file storing an array of town data objects, each containing a name, location, target OpenTTD population, and whether it is marked as a city in the game.
This document describes the standard format for this JSON file and outlines a workflow for creating this data effectively.
## Table of contents
- Why load external data?
- How to use this feature
- Creating geodata
- Town data format standards
- Town data values
- Loading geodata into OpenTTD
- Tutorial: Creating town data
## Why load external data?
There are three benefits to using an image editing program to create towns instead of the OpenTTD Scenario Editor.
1. Placing towns accurately is much easier using a map underlay such as OpenStreetMap to match town locations with the corresponding heightmap.
2. Storing town data in a JSON file instead of as an OpenTTD Scenario (.scn) doesn't require choosing your NewGRF house set before placing towns.
3. Town coordinates are scaled by the map size, so you can load the data onto whatever size map you like.
## How to use this feature
### Creating geodata
Town data is a text file in the JSON format, with a list of towns, each containing a coordinate location and properties: name, population, and whether or not it should be a city in OpenTTD.
The format of this file is standardized for importing into OpenTTD and must be followed for OpenTTD to properly parse the data.
For use in OpenTTD, you will also need a matching heightmap of the terrain features, as a PNG.
#### Town data format standards
The following code sample is complete and can be used in OpenTTD.
- The list of towns is enclosed in an array marked with square brackets `[]`
- Each town is enclosed in curly braces `{}`, with a comma after each town except for the last in the list.
- The properties separated by commas except for the last.
- Property names are enclosed in double quotes `""` with a colon `:` separating it from the property value.
- The name property value is enclosed in double quotes `"London"`, while all other property values `44910`, `true`, etc., are not.
```
[
{
"name": "London",
"population": 44910,
"city": true,
"x": 0.7998046875,
"y": 0.708984375
},
{
"name": "Canterbury",
"population": 217.16,
"city": false,
"x": 0.83251953125,
"y": 0.828125
}
]
```
#### Town data values
- Population is scaled down for use in OpenTTD. It is possible to generate huge cities by using a large number, but there is a practical limit to town size. The larger the town, the longer it will take to import town data, since towns are placed at a relatively small size and then expanded until the population is greater than the player-defined target.
- X and Y coordinates are a proportion of the total map dimension, between 0 and 1. Just take the pixel coordinates of the town's location in the corresponding heightmap (more detail in the tutorial below) and divide each by the maximum value.
- For example, London is at `726, 1638` in a 1024 px by 2048 px heightmap, so `726 / 1024 = 0.7998046875` and `1638 / 2048 = 0.708984375` gives the correct coordinates for OpenTTD.
- The reason for these proportional coordinates is so the data can be used for any map size.
- 0,0 is (approximately) the very top tile in OpenTTD. You can see tile coordinates in-game with the Land Info Tool.
- In most image editing programs, 0,0 is the top-left corner of the image. You can rotate the image however you want relative to compass north to orient the map to your liking. Make sure you crop and resize the image before recording town locations.
- In OpenTTD, X and Y axis are swapped compared to most image editing programs and the standard Cartesian coordinate system. From the 0,0 origin at top left, X is the axis along the left side and Y is the axis along the right side. You can still measure X and Y coordinates in your image editing program, just swap them before importing into OpenTTD or towns won't line up with your heightmap.
### Loading geodata into OpenTTD
Using geodata to create a real-world location in OpenTTD is done in the Scenario Editor.
1. Choose the NewGRFs you want to use in the game.
2. Load the heightmap which you created in the geodata workflow. Either rotation will work, but the clockwise rotation is considered "correct" and the coordinates in the Land Info Tool will match your data; counter clockwise maps will align properly but the coordinates won't match your data.
3. In the Town Generation window, click `Load from file` and choose the .json file containing town data. The default directory to search for town data is `OpenTTD\scenario\heightmap`.
4. (Optional) Manually add industries, rivers, trees, and objects.
5. Save the game as a Scenario and exit to the main menu.
6. Load the game with Play Scenario and enjoy.
Sometimes it's not possible to place a town, such as when the heightmap is very rough and a flat tile can't be found with a 16-tile radius of the target tile. In such cases, a sign will be placed on the target tile with the name of the town. The player can then place the town manually or change the heightmap settings and try again. This fallback also helps debug errors with data creation, such as if towns end up in the ocean.
## Tutorial: Creating town data
1. Load both your heightmap and a labeled map like OpenStreetMap as layers in an image editing program. You can use a free/open-source program like QGIS to acquire, align, and export these map images, if you like.
2. Crop the image to your desired bounds, ensuring the aspect ratio is supported in OpenTTD (1:1, 1:2, 1:4, etc.).
3. Resize the image to one of OpenTTD's supported map sizes, such as 512 px by 1024 px. Some image editors let you do this part of step 2. You can always load heightmaps and town data at a reduced size, so you may want to make this larger than your intended use in case you want it later.
4. Use the labeled map layer to find the pixel coordinates of each town you'd like to include in your map. In GIMP this is displayed in the bottom left corner of the image window, and in Photoshop you need to enable the Info panel (F8) and switch to pixel units of measurement if not already.
5. Some spreadsheets including Google Sheets can export data as JSON, so you may want to record it there, to export after step 8. Or you can build the JSON file manually.
6. Adjust population numbers for OpenTTD.
7. Change coordinates from pixels to proportion (0-1) of the total dimension: `x / maximum_x` and `y / maximum_y`, as described in "Town data values" above.
8. Swap X and Y coordinates before importing to OpenTTD, since OpenTTD uses a reverse X and Y system than most image editors.
9. Save the heightmap and town data files in your `OpenTTD\scenario\heightmap` folder.
@@ -79,8 +79,8 @@ the array so you can quickly see what is used and what is not.
<tr>
<tdrowspan="2">0</td>
<tdclass="caption">ground</td>
<tdclass="bits"rowspan=27><spanclass="used"title="Tile type">XXXX</span><spanclass="used"title="Presence and direction of bridge above">XX</span><spanclass="used"title="Tropic Zone: only meaningful in tropic climate. It contains the definition of the available zones">XX</span></td>
<tdclass="bits"rowspan=29><spanclass="used"title="Tile type">XXXX</span><spanclass="used"title="Presence and direction of bridge above">XX</span><spanclass="used"title="Tropic Zone: only meaningful in tropic climate. It contains the definition of the available zones">XX</span></td>
<tdclass="bits"><spanclass="used"title="Type of hedge on NE border">XXX</span><spanclass="used"title="Snow presence">X</span><spanclass="free">OOOO</span></td>
@@ -130,7 +130,7 @@ the array so you can quickly see what is used and what is not.
<tdclass="bits"><spanclass="used"title="Tile type: simple road (00), level crossing (01), road depot (10)">OO</span><spanclass="used"title="Disallow vehicles to go a specific direction">XX</span><spanclass="used"title="Road pieces">XXXX</span></td>
@@ -156,17 +156,17 @@ the array so you can quickly see what is used and what is not.
<tdclass="caption">finished house</td>
<tdclass="bits"rowspan=2><spanclass="used"title="House random bits">XXXX XXXX</span></td>
<tdclass="bits"rowspan=2><spanclass="pool"title="Town index on pool">XXXX XXXX XXXX XXXX</span></td>
<tdclass="bits"><spanclass="used"title="House is complete/in construction (see m5)">1</span><spanclass="used"title="House type (m4 + m3[6])">X</span><spanclass="free">O</span><spanclass="usable"title="Activated triggers (bits 2..4 don't have a meaning)">XXX</span><spanclass="used"title="Activated triggers (bits 2..4 don't have a meaning)">XX</span></td>
<tdclass="bits"rowspan=2><spanclass="used"title="House type (m4 + m3[6])">XXXX XXXX</span></td>
<tdclass="bits"><spanclass="used"title="House is complete/in construction (see m5)">1</span><spanclass="free">O</span><spanclass="used"title="The house is protected from the town upgrading it.">X</span><spanclass="usable"title="Activated triggers (bits 2..4 don't have a meaning)">XXX</span><spanclass="used"title="Activated triggers (bits 2..4 don't have a meaning)">XX</span></td>
<tdclass="bits"><spanclass="used"title="Age in years, clamped at 255">XXXX XXXX</span></td>
<tdclass="bits"rowspan=2><spanclass="abuse"title="Newhouses activated: periodic processing time remaining; if not, lift position for houses 04 and 05">XXXX XX</span><spanclass="free">OO</span></td>
<tdclass="bits"rowspan=2><spanclass="abuse"title="Newhouses activated: periodic processing time remaining; if not, lift position for houses 04 and 05">XXXX XX</span><spanclass="used"title="Animated tile state">XX</span></td>
<tdclass="bits"rowspan=2><spanclass="abuse"title="If newhouses active, m7 is the current animation frame">XXXX</span><spanclass="abuse"title="If newhouses active, m7 is the current animantion frame; if not, lift behaviour for houses 04 and 05">XXXX</span></td>
<tdclass="bits"><spanclass="used"title="House is complete/in construction (see m5)">O</span><spanclass="used"title="House type (m4 + m3[6])">X</span><spanclass="free">O</span><spanclass="usable"title="Activated triggers (bits 2..4 don't have a meaning)">XXX</span><spanclass="used"title="Activated triggers (bits 2..4 don't have a meaning)">XX</span></td>
<tdclass="bits"><spanclass="used"title="House is complete/in construction (see m5)">O</span><spanclass="used"title="House type (m4 + m3[6])">X</span><spanclass="used"title="The house is protected from the town upgrading it.">X</span><spanclass="usable"title="Activated triggers (bits 2..4 don't have a meaning)">XXX</span><spanclass="used"title="Activated triggers (bits 2..4 don't have a meaning)">XX</span></td>
<tdclass="bits"rowspan=8><spanclass="pool"title="Station index on pool">XXXX XXXX XXXX XXXX</span></td>
<tdclass="bits"rowspan=2><spanclass="used"title="Random bits">XXXX</span><spanclass="free">O</span><spanclass="used"title="May have pylons">X</span><spanclass="used"title="May have wires">X</span><spanclass="used"title="Tile is blocked">X</span></td>
<tdclass="bits"rowspan=2><spanclass="used"title="Custom station specifications ID">XXXX XXXX</span></td>
<tdclass="bits"rowspan=2><spanclass="used"title="May have pylons">X</span><spanclass="used"title="May have wires">X</span><spanclass="used"title="Station type">XXX</span><spanclass="used"title="Reserved track">X</span><spanclass="free">O</span><spanclass="used"title="Tile is blocked">X</span></td>
@@ -199,12 +199,17 @@ the array so you can quickly see what is used and what is not.
<tr>
<tdclass="caption">road stop</td>
<tdclass="bits"><spanclass="used"title="Owner of tram">XXXX</span><spanclass="free">OOOO</span></td>
<tdclass="bits"><spanclass="free">OO</span><spanclass="used"title="Roadtype for road stop">XX XXXX</span></td>
<tdclass="bits"><spanclass="usable"title="Graphics index">OOOO O</span><spanclass="used"title="Graphics index: 00 (exit towards NE), 01 (exit towards SE), 02 (exit towards SW), 03 (exit towards NW), 04 (drive through X), 05 (drive through Y)">XXX</span></td>
<tdclass="bits"><spanclass="free">OOO</span><spanclass="used"title="Owner of road">X XXXX</span></td>
<tdclass="bits"rowspan=2><spanclass="free">OO</span><spanclass="used"title="Roadtype for road stop">XX XXXX</span></td>
<tdclass="bits"rowspan=2><spanclass="usable"title="Graphics index">OOOO O</span><spanclass="used"title="Graphics index: 00 (exit towards NE), 01 (exit towards SE), 02 (exit towards SW), 03 (exit towards NW), 04 (drive through X), 05 (drive through Y)">XXX</span></td>
@@ -7,18 +7,20 @@ This guide is for OpenTTD developers/maintainers, to release a new version of Op
* If this is a beta version release, skip this step.
* If this is an RC1 (first Release Candidate) build, create a new branch `release/nn` where `nn` is the major version number, then apply changes similar to [PR#9573](https://github.com/OpenTTD/OpenTTD/pull/9573). You also need to forwardport the changelog, as in [PR#10113](https://github.com/OpenTTD/OpenTTD/pull/10113).
* Update CMakeLists.txt
* Add a new (empty) AI compatibility script in bin/ai/
* Add the new version to CheckAPIVersion in src/ai/ai_info.cpp + src/game/game_info.cpp
*Add the new version to src/script/api/ai_changelog.hpp + src/script/api/game_changelog.hpp
*Update the version of regression in bin/ai/regression/regression_info.nut
* Add a note to src/saveload/saveload.h about which savegame version is used in the branch.
* Update the version in `CMakeLists.txt` in the master branch, heading for the next major release, e.g. from 14.0 to 15.0.
* Add the new version to `ApiVersions` in `src/ai/ai_info.hpp` and `src/game/game_info.hpp`.
* Add the new version to `src/script/api/ai_changelog.hpp` and `src/script/api/game_changelog.hpp`.
*Update the version of regression in `bin/ai/regression/regression_info.nut`.
*Add a new (empty) AI compatibility script in `bin/ai/` and `bin/game/` for the version of the branch.
* Add a note to `src/saveload/saveload.h` about which savegame version is used in the branch.
* If this is a later RC or release build and the release branch already exists, you'll need to backport fixes and language from master to this branch, which were merged after the branch diverged from master. You can use these two helper scripts: https://github.com/OpenTTD/scripts/tree/main/backport
* If this is a maintenance release, update the version in `CMakeLists.txt` in the release branch, e.g. from 14.0 to 14.1.
## Step 1: Prepare changelog documentation
1. Update the [changelog](../changelog.txt) with new changes since the last release.
1. Update the [changelog](../changelog.md) with new changes since the last release.
* Changelog entries are typically PR titles, but can be edited to be more helpful without context.
* Don't include fixes to things which haven't previously been released (like fixes to features which are in the same changelog).
* Order the entries by importance: `Feature > Add > Change > Fix`, then numerically by PR number.
@@ -29,20 +31,26 @@ This guide is for OpenTTD developers/maintainers, to release a new version of Op
1. Go to https://github.com/OpenTTD/website/new/main/_posts and write a new announcement post. See a [previous example](https://github.com/OpenTTD/website/pull/238) for a template.
2. Create a new branch for this post and open a PR for it.
3. Write announcement text for socials like Forum/Discord/Twitter/Reddit and include it in the PR.
3. Write announcement text for the store pages and socials like TT-Forums / Discord / Twitter / Reddit / Fosstodon / etc., and include it in the PR.
4. Create a Steam news image for that post and include it in the PR.
5. Check the website post (preview link via checks page) and make corrections. We usually just use the GitHub web interface for this and squash the result later.
5. Check the website post ("View Deployment" link) and make corrections. We usually just use the GitHub web interface for this and squash the result later.
6. Get this PR approved, but do not merge yet.
## Step 3: Make the actual OpenTTD release
1.Go to https://github.com/OpenTTD/OpenTTD/releases/new and create a new tag matching the release number. For the body of the release, see any older release. "Set as a pre-release" for a beta or RC, set as latest for a real release.
2.Merge website PR.
3. Wait for the OpenTTD release checks to be complete.
4.Check that website links to the new release are working and correct, using the [staging website](https://www-staging.openttd.org/).
5. If this is a full release, ask orudge to update the Microsoft Store and TrueBrain to move the release from the "testing" to "default" branch on Steam.
1.Confirm that the version in `CMakeLists.txt` matches the intended release version.
2.Go to https://github.com/OpenTTD/OpenTTD/releases/new and create a new tag matching the release number. For the body of the release, copy in the changelog. "Set as a pre-release" for a beta or RC.
3. Wait for the OpenTTD release workflow to be complete.
4.If this is a full release:
* for `Steam`: under Steamworks -> SteamPipe -> Builds, set the "testing" branch live on the "default" branch. This will request 2FA validation.
* for `GOG`: under Builds, "Publish" the freshly uploaded builds to `Master`, `GOG-use only` and `Testing`.
* for `Microsoft Store`: ask orudge to publish the new release.
Access to `Steam`, `GOG` and/or `Microsoft Store` requires a developer account on that platform.
You will need access to the shared keystore in order to create such an account.
For help and/or access to either or both, please contact TrueBrain.
## Step 4: Tell the world
1.Tag and create a website release to trigger the actions that update the website.
2.After the website is live, make announcements on social media. You may need to coordinate with other developers who can make posts on Twitter, Reddit, Steam, and GOG.
1.Merge the website PR. This will publish the release post.
2.Make announcements on social media and store pages. You may need to coordinate with other developers who can make posts on TT-Forums, Twitter, Reddit, Fosstodon, Discord, Steam, GOG, Microsoft Store, etc.
All bugs listed below are marked as known. Please do not submit any bugs
that are the same as these. If you do, do not act surprised, because
we WILL flame you!
The current list of known bugs that we intend to fix can be found in our
bug tracking system at https://github.com/OpenTTD/OpenTTD/issues
Also check the closed bugs when searching for your bug in this system as we
might have fixed the bug in the mean time.
2.0) Known bugs
---- ----------------------------------
This section lists all known bugs that we do not intend to fix and the
reasons why we think that fixing them is infeasible. We might make some
minor improvements that reduce the scope of these bugs, but we will not
be able to completely fix them.
No suitable AI can be found:
If you have no AIs and an AI is started the so-called 'dummy' AI will
be loaded. This AI does nothing but writing a message on the AI debug
window and showing a red warning. There are basically two solutions
for this problem: Either you set the number of AI players to 0 so that
no AI is started. You find that setting at the top of the window in the
"AI / Game Scripts Settings" window.
The other solution is acquiring (downloading) some AI. The easiest way
to do this is via the "Check Online Content" button in the main (intro)
menu or directly in the "AI / Game Scripts Settings" dialogue via the
"Check Online Content" button.
After a while of playing, colours get corrupted:
In Windows 7 the background slideshow corrupts the colour mapping
of OpenTTD's 8bpp screen modes. Workarounds for this are:
a) Switching to windowed mode, instead of fullscreen
b) Switching off background slideshow
c) Setting up the 32bpp-anim or 32bpp-optimized blitter
Custom vehicle type name is incorrectly aligned:
Some NewGRFs use sprites that are bigger than normal in the "buy
vehicle" window. Due to this they have to encode an offset for
the vehicle type name. Upon renaming the vehicle type this encoded
offset is stripped from the name because the "edit box" cannot show
this encoding. As a result the custom vehicle type names will get
the default alignment. The only way to (partially) fix this is by
adding spaces to the custom name.
Clipping problems [#119]:
In some cases sprites are not drawn as one would expect. Examples of
this are aircraft that might be hidden below the runway or trees that
in some cases are rendered over vehicles.
The primary cause of this problem is that OpenTTD does not have enough
data (like a 3D model) to properly determine what needs to be drawn in
front of what. OpenTTD has bounding boxes but in lots of cases they
are either too big or too small and then cause problems with what
needs to be drawn in front of what. Also some visual tricks are used.
For example trains at 8 pixels high, the catenary needs to be drawn
above that. When you want to draw bridges on top of that, which are
only one height level (= 8 pixels) higher, you are getting into some
big problems.
We can not change the height levels; it would require us to either
redraw all vehicle or all landscape graphics. Doing so would mean we
leave the Transport Tycoon graphics, which in effect means OpenTTD
will not be a Transport Tycoon clone anymore.
Mouse scrolling not possible at the edges of the screen [#383] [#3966]:
Scrolling the viewport with the mouse cursor at the edges of the screen
in the same direction of the edge will fail. If the cursor is near the
edge the scrolling will be very slow.
OpenTTD only receives cursor position updates when the cursor is inside
OpenTTD's window. It is not told how far you have moved the cursor
outside of OpenTTD's window.
Lost trains ignore (block) exit signals [#1473]:
If trains are lost they ignore block exit signals, blocking junctions
with presignals. This is caused because the path finders cannot tell
where the train needs to go. As such a random direction is chosen at
each junction. This causes the trains to occasionally to make choices
that are unwanted from a player's point of view.
This will not be fixed because lost trains are in almost all cases a
network problem, e.g. a train can never reach a specific place. This
makes the impact of fixing the bug enormously small against the amount
of work needed to write a system that prevents the lost trains from
taking the wrong direction.
Vehicle owner of last transfer leg gets paid for all [#2427]:
When you make a transfer system that switches vehicle owners. This
is only possible with 'industry stations', e.g. the oil rig station
the owner of the vehicle that does the final delivery gets paid for
the whole trip. It is not shared amongst the different vehicle
owners that have participated in transporting the cargo.
This sharing is not done because it would enormously increase the
memory and CPU usage in big games for something that is happening
in only one corner case. We think it is not worth the effort until
sharing of stations is an official feature.
Forbid 90 degree turns does not work for crossing PBS paths [#2737]:
When you run a train through itself on a X junction with PBS turned on
the train will not obey the 'forbid 90 degree turns' setting. This is
due to the fact that we can not be sure that the setting was turned
off when the track was reserved, which means that we assume it was
turned on and that the setting does not hold at the time. We made it
this way to allow one to change the setting in-game, but it breaks
slightly when you are running your train through itself. Running a
train through means that your network is broken and is thus a user
error which OpenTTD tries to graciously handle.
Fixing this bug means that we need to record whether this particular
setting was turned on or off at the time the reservation was made. This
means adding quite a bit of data to the savegame for solving an issue
that is basically an user error. We think it is not worth the effort.
Duplicate (station) names after renaming [#3204]:
After renaming stations one can create duplicate station names. This
is done giving a station the same custom name as another station with
an automatically generated name.
The major part of this problem is that station names are translatable.
Meaning that a station is called e.g. '<TOWN> Central' in English and
'<TOWN> Centraal' in Dutch. This means that in network games the
renaming of a town could cause the rename to succeed on some clients
and fail at others. This creates an inconsistent game state that will
be seen as a 'desync'. Secondly the custom names are intended to fall
completely outside of the '<TOWN> <name>' naming of stations, so when
you rename a town all station names are updated accordingly.
As a result the decision has been made that all custom names are only
compared to the other custom names in the same class and not compared
to the automatically generated names.
Extreme CPU usage/hangs when using SDL and PulseAudio [#3294],
OpenTTD hangs/freezes when closing, OpenTTD is slow, OpenTTD uses a lot of CPU:
OpenTTD can be extremely slow/use a lot of CPU when the sound is
played via SDL and then through PulseAudio's ALSA wrapper. Under the
same configuration OpenTTD, or rather SDL, might hang when exiting
the game. This problem is seen most in Ubuntu 9.04 and higher.
This is because recent versions of the PulseAudio sound server
are configured to use timer-based audio scheduling rather than
interrupt-based audio scheduling. Configuring PulseAudio to force
use of interrupt-based scheduling may resolve sound problems for
some users. Under recent versions of Ubuntu Linux (9.04 and higher)
this can be accomplished by changing the following line in the
/etc/pulse/default.pa file:
load-module module-udev-detect
to
load-module module-udev-detect tsched=0
Note that PulseAudio must be restarted for changes to take effect. Older
versions of PulseAudio may use the module-hal-detect module instead.
Adding tsched=0 to the end of that line will have a similar effect.
Another possible solution is selecting the "pulse" backend of SDL
by either using "SDL_AUDIODRIVER=pulse openttd" at the command
prompt or installing the 'libsdl1.2debian-pulseaudio' package from
Ubuntu's Universe repository. For other distributions a similar
package needs to be installed.
OpenTTD not properly resizing with SDL on X [#3305]:
Under some X window managers OpenTTD's window does not properly
resize. You will either end up with a black bar at the right/bottom
side of the window or you cannot see the right/bottom of the window,
e.g. you cannot see the status bar. The problem is that OpenTTD does
not always receive a resize event from SDL making it impossible for
OpenTTD to know that the window was resized; sometimes moving the
window will solve the problem.
Window managers that are known to exhibit this behaviour are GNOME's
and KDE's. With the XFCE's and LXDE's window managers the resize
event is sent when the user releases the mouse.
Incorrect colours, crashes upon exit, debug warnings and smears upon
window resizing with SDL on macOS [#3447]:
Video handling with (lib)SDL under macOS is known to fail on some
versions of macOS with some hardware configurations. Some of
the problems happen only under some circumstances whereas others
are always present.
We suggest that the SDL video/sound backend is not used for OpenTTD
in combinations with macOS.
Train crashes entering same junction from block and path signals [#3928]:
When a train has reserved a path from a path signal to a two way
block signal and the reservation passes a path signal through the
back another train can enter the reserved path (only) via that
same two way block signal.
The reason for this has to do with optimisation; to fix this issue
the signal update has to pass all path signals until it finds either
a train or a backwards facing signal. This is a very expensive task.
The (signal) setups that allow these crashes can furthermore be
considered incorrectly signalled; one extra safe waiting point for
the train entering from path signal just after the backwards facing
signal (from the path signal train) resolves the issue.
Crashes when run in a VM using Parallels Desktop [#4003]:
When the Windows version of OpenTTD is executed in a VM under
Parallels Desktop a privileged instruction exception may be thrown.
As OpenTTD works natively on macOS as well as natively on Windows and
these native builds both don't exhibit this behaviour this crash is
most likely due to a bug in the virtual machine, something out of
the scope of OpenTTD. Most likely this is due to Parallels Desktop
lacking support for RDTSC calls. The problem can be avoided by using
other VM-software, Wine, or running natively on macOS.
Entry- and exit signals are not dragged [#4378]:
Unlike all other signal types, the entry- and exit signals are not
dragged but instead normal signals are placed on subsequent track
sections. This is done on purpose as this is the usually more
convenient solution. There are little to no occasions where more
than one entry or exit signal in a row are useful. This is different
for all other signal types where several in a row can serve one
purpose or another.
Station build date is incorrect [#4415]:
The tile query tool will show the date of the last (re)construction
at the station and not the date of the first construction. This is
due to compatibility reasons with NewGRFs and the fact that it is
wrong to say that the station is built in a particular year when it
was completely destroyed/rebuilt later on.
The tile query tool can be fixed by changing the "Build date" text
to "Date at which the last (re)construction took place" but this is
deemed too specific and long for that window.
(Temporary) wrong colours when switching to full screen [#4511]:
On Windows it can happen that you temporarily see wrong colours
when switching to full screen OpenTTD, either by starting
OpenTTD in full screen mode, changing to full screen mode or by
ALT-TAB-ing into a full screen OpenTTD. This is caused by the
fact that OpenTTD, by default, uses 8bpp paletted output. The
wrong colours you are seeing is a temporary effect of the video
driver switching to 8bpp palette mode.
This issue can be worked around in two ways:
a) Setting fullscreen_bpp to 32
b) Setting up the 32bpp-anim or 32bpp-optimized blitter
Can't run OpenTTD with the -d option from a MSYS console [#4587]:
The MSYS console does not allow OpenTTD to open an extra console for
debugging output. Compiling OpenTTD with the --enable-console
configure option prevents this issue and allows the -d option to use
the MSYS console for its output.
Unreadable characters for non-latin locales [#4607]:
OpenTTD does not ship a non-latin font in its graphics files. As a
result OpenTTD needs to acquire the font from somewhere else. What
OpenTTD does is ask the operating system, or a system library, for
the best font for a given language if the currently loaded font
does not provide all characters of the chosen translation. This
means that OpenTTD has no influence over the quality of the chosen
font; it just does the best it can do.
If the text is unreadable there are several steps that you can take
to improve this. The first step is finding a good font and configure
this in the configuration file. See section 9.0 of README.md for
more information. You can also increase the font size to make the
characters bigger and possible better readable.
If the problem is with the clarity of the font you might want to
enable anti-aliasing by setting the small_aa/medium_aa/large_aa
settings to "true". However, anti-aliasing only works when a 32-bit
blitter has been selected, e.g. blitter = "32bpp-anim", as with the
8 bits blitter there are not enough colours to properly perform the
anti-aliasing.
Train does not crash with itself [#4635]:
When a train drives in a circle the front engine passes through
wagons of the same train without crashing. This is intentional.
Signals are only aware of tracks, they do not consider the train
length and whether there would be enough room for a train in some
circle it might drive on. Also the path a train might take is not
necessarily known when passing a signal.
Checking all circumstances would take a lot of additional
computational power for signals, which is not considered worth
the effort, as it does not add anything to gameplay.
Nevertheless trains shall not crash in normal operation, so making
a train not crash with itself is the best solution for everyone.
Aircraft coming through wall in rotated airports [#4705]:
With rotated airports, specifically hangars, you will see that the
aircraft will show a part through the back wall of the hangar.
This can be solved by only drawing a part of the plane when being
at the back of the hangar, however then with transparency turned on
the aircraft would be shown partially which would be even weirder.
As such the current behaviour is deemed the least bad.
The same applies to overly long ships and their depots.
Vehicles not keeping their "maximum" speed [#4815]:
Vehicles that have not enough power to reach and maintain their
advertised maximum speed might be constantly jumping between two
speeds. This is due to the fact that speed and its calculations
are done with integral numbers instead of floating point numbers.
As a result of this a vehicle will never reach its equilibrium
between the drag/friction and propulsion. So in effect it will be
in a vicious circle of speeding up and slowing down due to being
just at the other side of the equilibrium.
Not speeding up when near the equilibrium will cause the vehicle to
never come in the neighbourhood of the equilibrium and not slowing
down when near the equilibrium will cause the vehicle to never slow
down towards the equilibrium once it has come down a hill.
It is possible to calculate whether the equilibrium will be passed,
but then all acceleration calculations need to be done twice.
Settings not saved when OpenTTD crashes [#4846]:
The settings are not saved when OpenTTD crashes for several reasons.
The most important is that the game state is broken and as such the
settings might contain invalid values, or the settings have not even
been loaded yet. This would cause invalid or totally wrong settings
to be written to the configuration file.
A solution to that would be saving the settings whenever one changes,
however due to the way the configuration file is saved this requires
a flush of the file to the disk and OpenTTD needs to wait till that
is finished. On some file system implementations this causes the
flush of all 'write-dirty' caches, which can be a significant amount
of data to be written. This can further be aggravated by spinning
down disks to conserve power, in which case this disk needs to be
spun up first. This means that many seconds may pass before the
configuration file is actually written, and all that time OpenTTD
will not be able to show any progress. Changing the way the
configuration file is saved is not an option as that leaves us more
vulnerable to corrupt configuration files.
Finally, crashes should not be happening. If they happen they should
be reported and fixed, so essentially fixing this is fixing the wrong
thing. If you really need the configuration changes to be saved,
and you need to run a version that crashes regularly, then you can
use the 'saveconfig' command in the console to save the settings.
Not all NewGRFs, AIs, game scripts are found [#4887]:
Under certain situations, where the path for the content within a
tar file is the same as other content on the file system or in another
tar file, it is possible that content is not found. A more thorough
explanation and solutions are described in section 4.4 of README.md.
Mouse cursor going missing with SDL [#4997]:
Under certain circumstances SDL does not notify OpenTTD of changes with
respect to the mouse pointer, specifically whether the mouse pointer
is within the bounds of OpenTTD or not. For example, if you "Alt-Tab"
to another application the mouse cursor will still be shown in OpenTTD,
and when you move the mouse outside of the OpenTTD window so the cursor
gets hidden, open/move another application on top of the OpenTTD window
and then Alt-tab back into OpenTTD the cursor will not be shown.
We cannot fix this problem as SDL simply does not provide the required
information in these corner cases. This is a bug in SDL and as such
there is little that we can do about it.
Trains might not stop at platforms that are currently being changed [#5553]:
If you add tiles to or remove tiles from a platform while a train is
approaching to stop at the same platform, that train can miss the place
where it's supposed to stop and pass the station without stopping.
This is caused by the fact that the train is considered to already
have stopped if it's beyond its assigned stopping location. We can't
let the train stop just anywhere in the station because then it would
never leave the station if you have the same station in the order
list multiple times in a row or if there is only one station
in theorder list (see #5684).
Some houses and industries are not affected by transparency [#5817]:
Some of the default houses and industries (f.e. the iron ore mine) are
not affected by the transparency options. This is because the graphics
do not (completely) separate the ground from the building.
This is a bug of the original graphics, and unfortunately cannot be
fixed with OpenGFX for the sake of maintaining compatibility with
the original graphics.
Involuntary cargo exchange with cargodist via neutral station [#6114]:
When two players serve a neutral station at an industry, a cross-company
chain for cargo flow can and will be established which can only be
interrupted if one of the players stops competing for the resources of
that industry. There is an easy fix for this: If you are loading at the
shared station make the order "no unload" and if you're unloading make
it "no load". Cargodist will then figure out that it should not create
such a route.
Incorrect ending year displayed in end of game newspaper [#8625]
The ending year of the game is configurable, but the date displayed in
the newspaper at the end of the game is part of the graphics, not text.
So to fix this would involve fixing the graphics in every baseset,
including the original. Additionally, basesets are free to put this
text in different positions (which they do), making a proper solution
to this infinitely more complex for a part of the game that fewer than
1% of players ever see.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.