mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2026-09-15 21:09:28 +00:00
Compare commits
267
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d76b3b296 | ||
|
|
bc6a656deb | ||
|
|
55157f6df2 | ||
|
|
9adc4bfc0f | ||
|
|
abf8438a1b | ||
|
|
92e895a37a | ||
|
|
046b0c6267 | ||
|
|
c1d37d8699 | ||
|
|
064f4df6cc | ||
|
|
6e65b2387a | ||
|
|
1445aa9543 | ||
|
|
1829f7926d | ||
|
|
2c91607671 | ||
|
|
22569515df | ||
|
|
06d3ae7381 | ||
|
|
ad63087928 | ||
|
|
bca8913d1d | ||
|
|
bd338d6e42 | ||
|
|
7e046f112b | ||
|
|
73b260ce05 | ||
|
|
43a82c2e27 | ||
|
|
c24526a2e1 | ||
|
|
595b696d61 | ||
|
|
faf3bb9739 | ||
|
|
e96f35cda9 | ||
|
|
66185a312d | ||
|
|
0600fbe34b | ||
|
|
84d89cc802 | ||
|
|
712ca5e3ec | ||
|
|
069833963c | ||
|
|
2675295675 | ||
|
|
91a12a3928 | ||
|
|
e15539c430 | ||
|
|
1810354622 | ||
|
|
ff578faf95 | ||
|
|
b9deabab7e | ||
|
|
fa0fd235c2 | ||
|
|
3e73a130d8 | ||
|
|
75aee10e1e | ||
|
|
67ded4f980 | ||
|
|
f1937222d3 | ||
|
|
c3f9cdf84f | ||
|
|
3b541d4c74 | ||
|
|
b4ac5e2231 | ||
|
|
5bd28fa692 | ||
|
|
26a84fad55 | ||
|
|
3555f26ae6 | ||
|
|
5533a24d84 | ||
|
|
316f36fe14 | ||
|
|
07177467b3 | ||
|
|
f128d0de1d | ||
|
|
84eb3fb0e0 | ||
|
|
74cb4dcefc | ||
|
|
c9b73247e0 | ||
|
|
7ffd3b2c48 | ||
|
|
e8dbd3aad2 | ||
|
|
f3b24d51c3 | ||
|
|
821a496495 | ||
|
|
9237685f4c | ||
|
|
98275ee5d3 | ||
|
|
4e24c205d6 | ||
|
|
98700eee43 | ||
|
|
62e568ce65 | ||
|
|
f0f964577d | ||
|
|
a321509d90 | ||
|
|
509cbedf0b | ||
|
|
a8b000f982 | ||
|
|
c3451b5d97 | ||
|
|
73660bfaf2 | ||
|
|
30955da3ce | ||
|
|
2cd5a241c5 | ||
|
|
2851c70a59 | ||
|
|
0f5a4290df | ||
|
|
e8ba7d0a08 | ||
|
|
e8d49ebfe6 | ||
|
|
7398d2e290 | ||
|
|
21329071df | ||
|
|
06d2f44891 | ||
|
|
05c40a6e55 | ||
|
|
d61a21cc0b | ||
|
|
2b24444146 | ||
|
|
459d213f74 | ||
|
|
2693e63247 | ||
|
|
7662105081 | ||
|
|
c38aa9cc86 | ||
|
|
dbe329733c | ||
|
|
120afd29f3 | ||
|
|
c4b16cb4cd | ||
|
|
ae413728c1 | ||
|
|
ca866cc083 | ||
|
|
aa6c694c67 | ||
|
|
744543e469 | ||
|
|
376a39f67a | ||
|
|
b563c34ca4 | ||
|
|
9c338cf212 | ||
|
|
d48463d2be | ||
|
|
f052ef213e | ||
|
|
94052a6ccb | ||
|
|
6d5f150b3d | ||
|
|
06d8e039c6 | ||
|
|
3befbdd52f | ||
|
|
8226548e31 | ||
|
|
f759b691d7 | ||
|
|
9001d4a884 | ||
|
|
00cdf1bc56 | ||
|
|
66b6d71e32 | ||
|
|
34bbae05db | ||
|
|
7c855c69fa | ||
|
|
8ea347a811 | ||
|
|
20fd2b5014 | ||
|
|
038c4d2b87 | ||
|
|
3f19240bbe | ||
|
|
3ebedecb4a | ||
|
|
3b02761302 | ||
|
|
534918ccb0 | ||
|
|
6295310f25 | ||
|
|
d1376d0b67 | ||
|
|
b43cdcba01 | ||
|
|
1522c9f661 | ||
|
|
7b703f688a | ||
|
|
a1920fc225 | ||
|
|
70bf84175f | ||
|
|
6ebe64703f | ||
|
|
2212169a8c | ||
|
|
6fc4bef0e3 | ||
|
|
813cde3735 | ||
|
|
06b830dc07 | ||
|
|
a19f6c02e5 | ||
|
|
e4b0e84a7c | ||
|
|
d6eff806f0 | ||
|
|
fd32d1447e | ||
|
|
5c89dff677 | ||
|
|
8e8eebd785 | ||
|
|
2396353c16 | ||
|
|
9f7f314f81 | ||
|
|
75ca1e3cda | ||
|
|
bf3a07c5d2 | ||
|
|
c627c64cc5 | ||
|
|
a949197264 | ||
|
|
8e055156e3 | ||
|
|
f935e34d90 | ||
|
|
a617d009cc | ||
|
|
c9fbc41636 | ||
|
|
6fdacb0759 | ||
|
|
4d40966303 | ||
|
|
97674ac2a2 | ||
|
|
632ab6a4e5 | ||
|
|
5d5d27841b | ||
|
|
9eacb889f8 | ||
|
|
42084ca516 | ||
|
|
3087194d80 | ||
|
|
8a8ebabb9d | ||
|
|
aa7eb089c6 | ||
|
|
dcc3a67752 | ||
|
|
f8aa2e64e4 | ||
|
|
8eaf511f0c | ||
|
|
c8220494de | ||
|
|
29136350cf | ||
|
|
ca8fb69ffd | ||
|
|
126669e10d | ||
|
|
5ed8f1203b | ||
|
|
ff674829f5 | ||
|
|
81530e2574 | ||
|
|
cb1c2409e6 | ||
|
|
37f737417c | ||
|
|
31eec7106b | ||
|
|
6d3f39609f | ||
|
|
380f9e8b48 | ||
|
|
e58fdb8840 | ||
|
|
f64e1cdae0 | ||
|
|
9307e1929e | ||
|
|
bfe5fb7339 | ||
|
|
0aaeb6f7e7 | ||
|
|
69ea970d6e | ||
|
|
5e7cb08411 | ||
|
|
910eeef17f | ||
|
|
18e28077cc | ||
|
|
41837d093b | ||
|
|
0b99a0b66a | ||
|
|
5822c8cc65 | ||
|
|
aa6fb0e9e5 | ||
|
|
f4f1beba64 | ||
|
|
6401855842 | ||
|
|
80e58e751a | ||
|
|
42c9f84d74 | ||
|
|
ecb761fc69 | ||
|
|
bec4e71d53 | ||
|
|
6ad7c1c40a | ||
|
|
484ed1008a | ||
|
|
2b164111a9 | ||
|
|
43e65d04e4 | ||
|
|
853dc245a0 | ||
|
|
1229a498b7 | ||
|
|
1278f62e2e | ||
|
|
71eba489bc | ||
|
|
a7b06fc9f5 | ||
|
|
29012c3fce | ||
|
|
13ab9c1adc | ||
|
|
69697a62d3 | ||
|
|
ce166bbbc3 | ||
|
|
70d4182850 | ||
|
|
030bbc6399 | ||
|
|
d07ff71c67 | ||
|
|
20067d2db5 | ||
|
|
2ab3b5516f | ||
|
|
1ac5baab31 | ||
|
|
bff850128c | ||
|
|
2aaffbe23c | ||
|
|
68e37b7b50 | ||
|
|
264cbd8ab5 | ||
|
|
17fbe0b911 | ||
|
|
2d13bcb7b9 | ||
|
|
d54bf49936 | ||
|
|
262c364a28 | ||
|
|
129825077b | ||
|
|
445d2b3e22 | ||
|
|
f487cde056 | ||
|
|
5dea170589 | ||
|
|
faacae2c3f | ||
|
|
26fef5b62b | ||
|
|
f2f6609206 | ||
|
|
5f20a97b36 | ||
|
|
7d252ff7fc | ||
|
|
7240ed5817 | ||
|
|
c111abad37 | ||
|
|
52e97c981c | ||
|
|
313c6c45aa | ||
|
|
1779da51c2 | ||
|
|
3ac1a2f1e4 | ||
|
|
0715903b24 | ||
|
|
748700bd9e | ||
|
|
96b59af4d1 | ||
|
|
3356aa7c69 | ||
|
|
ee664f7e8c | ||
|
|
b1dc37fb05 | ||
|
|
3317997976 | ||
|
|
d095526406 | ||
|
|
fe9093df96 | ||
|
|
e10200efa4 | ||
|
|
eb09d18418 | ||
|
|
033114da8c | ||
|
|
5f84ff5c3f | ||
|
|
43842f0bcc | ||
|
|
16cd420e4c | ||
|
|
89a90080c5 | ||
|
|
80541a7682 | ||
|
|
f82bd95faf | ||
|
|
64dbb9383b | ||
|
|
244a267304 | ||
|
|
a2f3d59707 | ||
|
|
122023be8d | ||
|
|
6613da5d7e | ||
|
|
8d96ea1a5e | ||
|
|
4ed4a8b602 | ||
|
|
5d15c8b8ab | ||
|
|
f3951214c1 | ||
|
|
80f672d5b4 | ||
|
|
5602555a7a | ||
|
|
736998b595 | ||
|
|
7d4282b341 | ||
|
|
dd426bb8c7 | ||
|
|
7a6e04561d | ||
|
|
fce2748bb7 | ||
|
|
960b840291 | ||
|
|
73045f9b0e | ||
|
|
4c77026167 | ||
|
|
ff5e067341 |
@@ -10,3 +10,5 @@ query-filters:
|
||||
- cpp/irregular-enum-init
|
||||
# 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.
|
||||
- cpp/trivial-switch
|
||||
# Our (GUI) code tends to use long switches.
|
||||
- cpp/long-switch
|
||||
|
||||
@@ -8,3 +8,5 @@ updates:
|
||||
actions:
|
||||
patterns:
|
||||
- "*"
|
||||
commit-message:
|
||||
prefix: "Upgrade: "
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Fix dubious ownership
|
||||
run: |
|
||||
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup vcpkg
|
||||
uses: ./.github/actions/setup-vcpkg
|
||||
@@ -78,15 +78,15 @@ jobs:
|
||||
mkdir -p ~/.local/share/openttd/baseset
|
||||
cd ~/.local/share/openttd/baseset
|
||||
|
||||
echo "::group::Download OpenGFX"
|
||||
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
|
||||
echo "::group::Download OpenGFX2"
|
||||
curl -L https://cdn.openttd.org/opengfx2_classic-releases/0.8/opengfx2_classic-0.8-all.zip -o opengfx2-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Unpack OpenGFX"
|
||||
unzip opengfx-all.zip
|
||||
echo "::group::Unpack OpenGFX2"
|
||||
unzip opengfx2-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
rm -f opengfx-all.zip
|
||||
rm -f opengfx2-all.zip
|
||||
|
||||
- name: Install GCC problem matcher
|
||||
uses: ammaraskar/gcc-problem-matcher@master
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
xcode-version: latest-stable
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup vcpkg
|
||||
uses: ./.github/actions/setup-vcpkg
|
||||
@@ -45,15 +45,15 @@ jobs:
|
||||
mkdir -p ~/Documents/OpenTTD/baseset
|
||||
cd ~/Documents/OpenTTD/baseset
|
||||
|
||||
echo "::group::Download OpenGFX"
|
||||
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
|
||||
echo "::group::Download OpenGFX2"
|
||||
curl -L https://cdn.openttd.org/opengfx2_classic-releases/0.8/opengfx2_classic-0.8-all.zip -o opengfx2-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Unpack OpenGFX"
|
||||
unzip opengfx-all.zip
|
||||
echo "::group::Unpack OpenGFX2"
|
||||
unzip opengfx2-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
rm -f opengfx-all.zip
|
||||
rm -f opengfx2-all.zip
|
||||
|
||||
- name: Install GCC problem matcher
|
||||
uses: ammaraskar/gcc-problem-matcher@master
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
@@ -47,15 +47,15 @@ jobs:
|
||||
mkdir -p "C:/Users/Public/Documents/OpenTTD/baseset"
|
||||
cd "C:/Users/Public/Documents/OpenTTD/baseset"
|
||||
|
||||
echo "::group::Download OpenGFX"
|
||||
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
|
||||
echo "::group::Download OpenGFX2"
|
||||
curl -L https://cdn.openttd.org/opengfx2_classic-releases/0.8/opengfx2_classic-0.8-all.zip -o opengfx2-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Unpack OpenGFX"
|
||||
unzip opengfx-all.zip
|
||||
echo "::group::Unpack OpenGFX2"
|
||||
unzip opengfx2-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
rm -f opengfx-all.zip
|
||||
rm -f opengfx2-all.zip
|
||||
|
||||
- name: Install GCC problem matcher
|
||||
uses: ammaraskar/gcc-problem-matcher@master
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup vcpkg
|
||||
uses: ./.github/actions/setup-vcpkg
|
||||
@@ -31,15 +31,15 @@ jobs:
|
||||
mkdir -p "C:/Users/Public/Documents/OpenTTD/baseset"
|
||||
cd "C:/Users/Public/Documents/OpenTTD/baseset"
|
||||
|
||||
echo "::group::Download OpenGFX"
|
||||
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
|
||||
echo "::group::Download OpenGFX2"
|
||||
curl -L https://cdn.openttd.org/opengfx2_classic-releases/0.8/opengfx2_classic-0.8-all.zip -o opengfx2-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Unpack OpenGFX"
|
||||
unzip opengfx-all.zip
|
||||
echo "::group::Unpack OpenGFX2"
|
||||
unzip opengfx2-all.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
rm -f opengfx-all.zip
|
||||
rm -f opengfx2-all.zip
|
||||
|
||||
- name: Install MSVC problem matcher
|
||||
uses: ammaraskar/msvc-problem-matcher@master
|
||||
|
||||
@@ -21,10 +21,11 @@ jobs:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
packages: read
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup vcpkg
|
||||
uses: ./.github/actions/setup-vcpkg
|
||||
@@ -76,7 +77,7 @@ jobs:
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: cpp
|
||||
config-file: ./.github/codeql/codeql-config.yml
|
||||
@@ -92,7 +93,7 @@ jobs:
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: /language:cpp
|
||||
upload: False
|
||||
@@ -110,6 +111,6 @@ jobs:
|
||||
output: sarif-results/cpp.sarif
|
||||
|
||||
- name: Upload results
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
uses: github/codeql-action/upload-sarif@v4
|
||||
with:
|
||||
sarif_file: sarif-results/cpp.sarif
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 4
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
@@ -78,7 +78,7 @@ jobs:
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: openttd-docs
|
||||
path: build/bundles/*.tar.xz
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
@@ -156,14 +156,14 @@ jobs:
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: openttd-linux-generic
|
||||
path: build/bundles
|
||||
retention-days: 5
|
||||
|
||||
- name: Store symbols
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: symbols-linux-generic
|
||||
path: build/symbols
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
xcode-version: latest-stable
|
||||
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
@@ -205,14 +205,14 @@ jobs:
|
||||
mv _CPack_Packages/*/Bundle/openttd-*.zip bundles/
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: openttd-macos-universal
|
||||
path: build-x64/bundles
|
||||
retention-days: 5
|
||||
|
||||
- name: Store symbols
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: symbols-macos-universal
|
||||
path: build-x64/symbols
|
||||
|
||||
@@ -30,14 +30,14 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout (Release)
|
||||
if: github.event_name == 'release'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
# We generate a changelog; for this we need the full git log.
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Checkout (Manual)
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
# We generate a changelog; for this we need the full git log.
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
|
||||
- name: Checkout (Trigger)
|
||||
if: github.event_name == 'repository_dispatch'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.client_payload.ref }}
|
||||
# We generate a changelog; for this we need the full git log.
|
||||
@@ -202,14 +202,14 @@ jobs:
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: openttd-source
|
||||
path: build/bundles/*
|
||||
retention-days: 5
|
||||
|
||||
- name: Store source (for other jobs)
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: internal-source
|
||||
path: source.tar.gz
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
@@ -25,17 +25,17 @@ jobs:
|
||||
tar -xf source.tar.gz --strip-components=1
|
||||
|
||||
- name: Download x86 build
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: openttd-windows-x86
|
||||
|
||||
- name: Download x64 build
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: openttd-windows-x64
|
||||
|
||||
- name: Download arm64 build
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: openttd-windows-arm64
|
||||
|
||||
@@ -74,16 +74,16 @@ jobs:
|
||||
mkdir -p builds/common-binaries/baseset
|
||||
cd builds/common-binaries/baseset
|
||||
|
||||
echo "::group::Download OpenGFX"
|
||||
curl -L https://cdn.openttd.org/opengfx-releases/7.1/opengfx-7.1-all.zip -o opengfx-all.zip
|
||||
echo "::group::Download OpenGFX2"
|
||||
curl -L https://cdn.openttd.org/opengfx2_classic-releases/0.8/opengfx2_classic-0.8-all.zip -o opengfx2_classic.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Unpack OpenGFX"
|
||||
unzip opengfx-all.zip
|
||||
tar xf opengfx-*.tar
|
||||
echo "::group::Unpack OpenGFX2"
|
||||
unzip opengfx2_classic.zip
|
||||
tar xf OpenGFX2_Classic-0.8.tar
|
||||
echo "::endgroup::"
|
||||
|
||||
rm -f opengfx-all.zip opengfx-*.tar
|
||||
rm -f opengfx2_classic.zip OpenGFX2_Classic-0.8.tar
|
||||
|
||||
- name: Install OpenMSX
|
||||
shell: bash
|
||||
@@ -185,7 +185,7 @@ jobs:
|
||||
move output\OpenTTD.appxbundle bundles\internal\openttd-${{ inputs.version }}-windows-store.appxbundle
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: openttd-windows-store
|
||||
path: builds/bundles
|
||||
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: internal-source
|
||||
|
||||
@@ -194,14 +194,14 @@ jobs:
|
||||
AZURE_CODESIGN_PROFILE_NAME: ${{ secrets.AZURE_CODESIGN_PROFILE_NAME }}
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: openttd-windows-${{ matrix.arch }}
|
||||
path: build/bundles
|
||||
retention-days: 5
|
||||
|
||||
- name: Store symbols
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: symbols-windows-${{ matrix.arch }}
|
||||
path: build/symbols
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check for finding script functions that require company/deity mode enforcement/checks
|
||||
run: |
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check for unused strings
|
||||
run: |
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download all bundles
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
|
||||
- name: Calculate checksums
|
||||
run: |
|
||||
@@ -70,14 +70,14 @@ jobs:
|
||||
done
|
||||
|
||||
- name: Store bundles
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: cdn-bundles
|
||||
path: bundles/*
|
||||
retention-days: 5
|
||||
|
||||
- name: Store breakpad symbols
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: cdn-symbols
|
||||
path: symbols/*
|
||||
@@ -130,7 +130,7 @@ jobs:
|
||||
installation_retrieval_payload: "OpenTTD/workflows"
|
||||
|
||||
- name: Trigger 'Publish Docs'
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
uses: peter-evans/repository-dispatch@v4
|
||||
with:
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
repository: OpenTTD/workflows
|
||||
|
||||
@@ -15,31 +15,31 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: internal-source
|
||||
path: internal-source
|
||||
|
||||
- name: Download bundle (Windows x86)
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: openttd-windows-x86
|
||||
path: openttd-windows-x86
|
||||
|
||||
- name: Download bundle (Windows x64)
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: openttd-windows-x64
|
||||
path: openttd-windows-x64
|
||||
|
||||
- name: Download bundle (MacOS)
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: openttd-macos-universal
|
||||
path: openttd-macos-universal
|
||||
|
||||
- name: Download bundle (Linux)
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: openttd-linux-generic
|
||||
path: openttd-linux-generic
|
||||
@@ -56,16 +56,16 @@ jobs:
|
||||
mkdir -p gog/opengfx/baseset
|
||||
cd gog/opengfx/baseset
|
||||
|
||||
echo "::group::Download OpenGFX"
|
||||
curl -L https://cdn.openttd.org/opengfx-releases/7.1/opengfx-7.1-all.zip -o opengfx-all.zip
|
||||
echo "::group::Download OpenGFX2"
|
||||
curl -L https://cdn.openttd.org/opengfx2_classic-releases/0.8/opengfx2_classic-0.8-all.zip -o opengfx2_classic.zip
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Unpack OpenGFX"
|
||||
unzip opengfx-all.zip
|
||||
tar xf opengfx-*.tar
|
||||
echo "::group::Unpack OpenGFX2"
|
||||
unzip opengfx2_classic.zip
|
||||
tar xf OpenGFX2_Classic-0.8.tar
|
||||
echo "::endgroup::"
|
||||
|
||||
rm -f opengfx-all.zip opengfx-*.tar
|
||||
rm -f opengfx2_classic.zip OpenGFX2_Classic-0.8.tar
|
||||
|
||||
- name: Install OpenMSX
|
||||
shell: bash
|
||||
|
||||
@@ -18,31 +18,31 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download source
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: internal-source
|
||||
path: internal-source
|
||||
|
||||
- name: Download bundle (Windows x86)
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: openttd-windows-x86
|
||||
path: openttd-windows-x86
|
||||
|
||||
- name: Download bundle (Windows x64)
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: openttd-windows-x64
|
||||
path: openttd-windows-x64
|
||||
|
||||
- name: Download bundle (MacOS)
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: openttd-macos-universal
|
||||
path: openttd-macos-universal
|
||||
|
||||
- name: Download bundle (Linux)
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: openttd-linux-generic
|
||||
path: openttd-linux-generic
|
||||
|
||||
@@ -196,6 +196,29 @@ These include:
|
||||
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.
|
||||
|
||||
|
||||
## Project goals
|
||||
|
||||
### What are the goals of the official branch?
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ GNU General Public License
|
||||
|
||||
_Version 2, June 1991_
|
||||
_Copyright © 1989, 1991 Free Software Foundation, Inc.,_
|
||||
_51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA_
|
||||
_[https://fsf.org/](https://fsf.org/)_
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@@ -25,6 +25,12 @@ if(EDITBIN_EXECUTABLE)
|
||||
execute_process(COMMAND ${EDITBIN_EXECUTABLE} /nologo /subsystem:console ${OPENTTD_EXECUTABLE})
|
||||
endif()
|
||||
|
||||
# Remove previous crash files
|
||||
file(GLOB CRASH_FILES "regression/crash*")
|
||||
if(CRASH_FILES)
|
||||
file(REMOVE ${CRASH_FILES})
|
||||
endif()
|
||||
|
||||
# Run the regression test
|
||||
execute_process(COMMAND ${OPENTTD_EXECUTABLE}
|
||||
-x
|
||||
@@ -40,6 +46,13 @@ execute_process(COMMAND ${OPENTTD_EXECUTABLE}
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# Detect any crash
|
||||
file(GLOB CRASH_FILES "regression/crash*.log")
|
||||
if (CRASH_FILES)
|
||||
file(READ ${CRASH_FILES} CRASH_LOG)
|
||||
message(FATAL_ERROR "OpenTTD crashed: ${CRASH_LOG}")
|
||||
endif()
|
||||
|
||||
if(REGRESSION_OUTPUT)
|
||||
message(FATAL_ERROR "Unexpected output: ${REGRESSION_OUTPUT}")
|
||||
endif()
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
eb8390a0569e66ec417c64ad254f9d05
|
||||
c56aad31380c077d619e124bd87c8270
|
||||
|
||||
@@ -10,6 +10,7 @@ if(GRFCODEC_FOUND)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/airport_preview.nfo
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/aqueduct.nfo
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/autorail.nfo
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bridge_decks.nfo
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/canals.nfo
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/chars.nfo
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elrails.nfo
|
||||
@@ -31,6 +32,8 @@ if(GRFCODEC_FOUND)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/airport_preview.png
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/aqueduct.png
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/autorail.png
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bridge_decks.png
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bridge_decks_toyland.png
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/canals.png
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/canal_locks.png
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/chars.png
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// This file is part of OpenTTD.
|
||||
// OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
// OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
-1 * 0 0C "Bridge decks"
|
||||
-1 * 0 07 83 01 \7= 03 19
|
||||
-1 * 3 05 1B 18
|
||||
|
||||
-1 sprites/bridge_decks.png 8bpp 96 16 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 16 16 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 176 16 64 39 -31 -8 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 256 16 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 336 16 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 416 16 64 39 -31 -8 normal
|
||||
|
||||
-1 sprites/bridge_decks.png 8bpp 96 71 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 16 71 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 176 71 64 39 -31 -8 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 256 71 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 336 71 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 416 71 64 39 -31 -8 normal
|
||||
|
||||
-1 sprites/bridge_decks.png 8bpp 96 126 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 16 126 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 176 126 64 39 -31 -8 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 256 126 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 336 126 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 416 126 64 39 -31 -8 normal
|
||||
|
||||
// X and Y axis are swapped for road surface.
|
||||
-1 sprites/bridge_decks.png 8bpp 16 181 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 96 181 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 176 181 64 39 -31 -8 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 256 181 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 336 181 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks.png 8bpp 416 181 64 39 -31 -8 normal
|
||||
|
||||
// Toyland bridge decks, skip if not toyland.
|
||||
-1 * 0 07 83 01 \7! 03 19
|
||||
-1 * 3 05 1B 18
|
||||
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 96 16 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 16 16 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 176 16 64 39 -31 -8 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 256 16 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 336 16 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 416 16 64 39 -31 -8 normal
|
||||
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 96 71 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 16 71 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 176 71 64 39 -31 -8 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 256 71 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 336 71 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 416 71 64 39 -31 -8 normal
|
||||
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 96 126 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 16 126 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 176 126 64 39 -31 -8 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 256 126 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 336 126 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 416 126 64 39 -31 -8 normal
|
||||
|
||||
// X and Y axis are swapped for road surface.
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 16 181 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 96 181 64 31 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 176 181 64 39 -31 -8 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 256 181 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 336 181 64 23 -31 0 normal
|
||||
-1 sprites/bridge_decks_toyland.png 8bpp 416 181 64 39 -31 -8 normal
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
@@ -100,3 +100,4 @@
|
||||
#include "palette.nfo"
|
||||
#include "road_waypoints.nfo"
|
||||
#include "overlay_rocks.nfo"
|
||||
#include "bridge_decks.nfo"
|
||||
|
||||
@@ -461,6 +461,21 @@ function Regression::Company()
|
||||
}
|
||||
}
|
||||
|
||||
function Regression::CompanyGender()
|
||||
{
|
||||
print("");
|
||||
print("--Company Gender--");
|
||||
/* Check gender switching behaviour matches API. */
|
||||
print(" GetPresidentGender(): " + AICompany.GetPresidentGender(AICompany.COMPANY_SELF));
|
||||
print(" SetPresidentGender(): " + AICompany.SetPresidentGender(AICompany.GENDER_MALE));
|
||||
print(" GetPresidentGender(): " + AICompany.GetPresidentGender(AICompany.COMPANY_SELF));
|
||||
print(" SetPresidentGender(): " + AICompany.SetPresidentGender(AICompany.GENDER_FEMALE));
|
||||
print(" GetPresidentGender(): " + AICompany.GetPresidentGender(AICompany.COMPANY_SELF));
|
||||
/* Setting to existing gender should fail. */
|
||||
print(" SetPresidentGender(): " + AICompany.SetPresidentGender(AICompany.GENDER_FEMALE));
|
||||
print(" GetPresidentGender(): " + AICompany.GetPresidentGender(AICompany.COMPANY_SELF));
|
||||
}
|
||||
|
||||
function Regression::Engine()
|
||||
{
|
||||
local j = 0;
|
||||
@@ -487,6 +502,13 @@ function Regression::Engine()
|
||||
print(" GetRailType(): " + AIEngine.GetRailType(i));
|
||||
print(" GetRoadType(): " + AIEngine.GetRoadType(i));
|
||||
print(" GetPlaneType(): " + AIEngine.GetPlaneType(i));
|
||||
local railtypes = AIEngine.GetAllRailTypes(i);
|
||||
print(" GetAllRailTypes(): " + (railtypes == null ? "null" : "instance"));
|
||||
if (railtypes != null) {
|
||||
foreach(t in railtypes) {
|
||||
print(" " + t);
|
||||
}
|
||||
}
|
||||
}
|
||||
print(" Valid Engines: " + j);
|
||||
}
|
||||
@@ -2089,6 +2111,7 @@ function Regression::Start()
|
||||
this.Vehicle();
|
||||
/* Order has to be after Vehicle */
|
||||
this.Order();
|
||||
this.CompanyGender();
|
||||
print("");
|
||||
print(" First Subsidy Test");
|
||||
PrintSubsidy(0);
|
||||
|
||||
+529
-246
File diff suppressed because it is too large
Load Diff
+7
-4
@@ -18,7 +18,8 @@ void sqstd_printcallstack(HSQUIRRELVM v)
|
||||
SQFloat f;
|
||||
SQInteger level=1; //1 is to skip this function that is level 0
|
||||
SQInteger seq=0;
|
||||
pf(v,"\nCALLSTACK\n");
|
||||
pf(v,"\n");
|
||||
pf(v,"CALLSTACK\n");
|
||||
while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si)))
|
||||
{
|
||||
std::string_view fn="unknown";
|
||||
@@ -37,7 +38,8 @@ void sqstd_printcallstack(HSQUIRRELVM v)
|
||||
level++;
|
||||
}
|
||||
level=0;
|
||||
pf(v,"\nLOCALS\n");
|
||||
pf(v,"\n");
|
||||
pf(v,"LOCALS\n");
|
||||
|
||||
for(level=0;level<10;level++){
|
||||
seq=0;
|
||||
@@ -116,11 +118,12 @@ static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v)
|
||||
if(pf) {
|
||||
std::string_view error;
|
||||
if(sq_gettop(v)>=1) {
|
||||
pf(v,"\n");
|
||||
if(SQ_SUCCEEDED(sq_getstring(v,2,error))) {
|
||||
pf(v,fmt::format("\nAN ERROR HAS OCCURRED [{}]\n",error));
|
||||
pf(v,fmt::format("AN ERROR HAS OCCURRED [{}]\n",error));
|
||||
}
|
||||
else{
|
||||
pf(v,"\nAN ERROR HAS OCCURRED [unknown]\n");
|
||||
pf(v,"AN ERROR HAS OCCURRED [unknown]\n");
|
||||
}
|
||||
sqstd_printcallstack(v);
|
||||
}
|
||||
|
||||
+2
-2
@@ -58,7 +58,7 @@ HSQUIRRELVM sq_open(SQInteger initialstacksize)
|
||||
SQVM *v;
|
||||
sq_new(ss, SQSharedState);
|
||||
v = (SQVM *)SQ_MALLOC(sizeof(SQVM));
|
||||
new (v) SQVM(ss);
|
||||
new (v, sizeof(SQVM)) SQVM(ss);
|
||||
ss->_root_vm = v;
|
||||
if(v->Init(nullptr, initialstacksize)) {
|
||||
return v;
|
||||
@@ -76,7 +76,7 @@ HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize)
|
||||
ss=_ss(friendvm);
|
||||
|
||||
v= (SQVM *)SQ_MALLOC(sizeof(SQVM));
|
||||
new (v) SQVM(ss);
|
||||
new (v, sizeof(SQVM)) SQVM(ss);
|
||||
|
||||
if(v->Init(friendvm, initialstacksize)) {
|
||||
friendvm->Push(v);
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ private:
|
||||
public:
|
||||
static SQArray* Create(SQSharedState *ss,SQInteger nInitialSize){
|
||||
SQArray *newarray=(SQArray*)SQ_MALLOC(sizeof(SQArray));
|
||||
new (newarray) SQArray(ss,nInitialSize);
|
||||
new (newarray, sizeof(SQArray)) SQArray(ss,nInitialSize);
|
||||
return newarray;
|
||||
}
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
|
||||
+3
-3
@@ -34,7 +34,7 @@ struct SQClass : public CHAINABLE_OBJ
|
||||
public:
|
||||
static SQClass* Create(SQSharedState *ss,SQClass *base) {
|
||||
SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass));
|
||||
new (newclass) SQClass(ss, base);
|
||||
new (newclass, sizeof(SQClass)) SQClass(ss, base);
|
||||
return newclass;
|
||||
}
|
||||
~SQClass();
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
|
||||
SQInteger size = calcinstancesize(theclass);
|
||||
SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
|
||||
new (newinst) SQInstance(ss, theclass,size);
|
||||
new (newinst, size) SQInstance(ss, theclass,size);
|
||||
if(theclass->_udsize) {
|
||||
newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize);
|
||||
}
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
{
|
||||
SQInteger size = calcinstancesize(_class);
|
||||
SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
|
||||
new (newinst) SQInstance(ss, this,size);
|
||||
new (newinst, size) SQInstance(ss, this,size);
|
||||
if(_class->_udsize) {
|
||||
newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize);
|
||||
}
|
||||
|
||||
+3
-3
@@ -11,7 +11,7 @@ private:
|
||||
public:
|
||||
static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func){
|
||||
SQClosure *nc=(SQClosure*)SQ_MALLOC(sizeof(SQClosure));
|
||||
new (nc) SQClosure(ss,func);
|
||||
new (nc, sizeof(SQClosure)) SQClosure(ss,func);
|
||||
return nc;
|
||||
}
|
||||
void Release() override {
|
||||
@@ -49,7 +49,7 @@ private:
|
||||
public:
|
||||
static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){
|
||||
SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator));
|
||||
new (nc) SQGenerator(ss,closure);
|
||||
new (nc, sizeof(SQGenerator)) SQGenerator(ss,closure);
|
||||
return nc;
|
||||
}
|
||||
~SQGenerator()
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func)
|
||||
{
|
||||
SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(sizeof(SQNativeClosure));
|
||||
new (nc) SQNativeClosure(ss,func);
|
||||
new (nc, sizeof(SQNativeClosure)) SQNativeClosure(ss,func);
|
||||
return nc;
|
||||
}
|
||||
SQNativeClosure *Clone()
|
||||
|
||||
+3
-2
@@ -99,8 +99,9 @@ public:
|
||||
{
|
||||
SQFunctionProto *f;
|
||||
//I compact the whole class and members in a single memory allocation
|
||||
f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams));
|
||||
new (f) SQFunctionProto(ninstructions, nliterals, nparameters, nfunctions, noutervalues, nlineinfos, nlocalvarinfos, ndefaultparams);
|
||||
SQInteger size = _FUNC_SIZE(ninstructions, nliterals, nparameters, nfunctions, noutervalues, nlineinfos, nlocalvarinfos, ndefaultparams);
|
||||
f = (SQFunctionProto *)sq_vm_malloc(size);
|
||||
new (f, size) SQFunctionProto(ninstructions, nliterals, nparameters, nfunctions, noutervalues, nlineinfos, nlocalvarinfos, ndefaultparams);
|
||||
return f;
|
||||
}
|
||||
void Release() override {
|
||||
|
||||
+2
-1
@@ -91,7 +91,8 @@ SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx)
|
||||
SQWeakRef *SQRefCounted::GetWeakRef(SQObjectType type)
|
||||
{
|
||||
if(!_weakref) {
|
||||
sq_new(_weakref,SQWeakRef);
|
||||
_weakref = (SQWeakRef *)sq_vm_malloc(sizeof(SQWeakRef));
|
||||
new (_weakref, sizeof(SQWeakRef)) SQWeakRef();
|
||||
_weakref->_obj._type = type;
|
||||
_weakref->_obj._unVal.pRefCounted = this;
|
||||
}
|
||||
|
||||
+5
-8
@@ -64,22 +64,19 @@ struct SQRefCounted
|
||||
virtual void Release()=0;
|
||||
|
||||
/* Placement new/delete to prevent memory leaks if constructor throws an exception. */
|
||||
inline void *operator new(size_t size, SQRefCounted *place)
|
||||
inline void *operator new([[maybe_unused]] size_t size, void *ptr, [[maybe_unused]] size_t real_size)
|
||||
{
|
||||
place->size = size;
|
||||
return place;
|
||||
assert(size <= real_size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
inline void operator delete(void *ptr, SQRefCounted *place)
|
||||
inline void operator delete(void *ptr, void *, size_t real_size)
|
||||
{
|
||||
SQ_FREE(ptr, place->size);
|
||||
SQ_FREE(ptr, real_size);
|
||||
}
|
||||
|
||||
/* Never used but required. */
|
||||
inline void operator delete(void *) { NOT_REACHED(); }
|
||||
|
||||
private:
|
||||
size_t size = 0;
|
||||
};
|
||||
|
||||
struct SQWeakRef : SQRefCounted
|
||||
|
||||
+1
-1
@@ -553,7 +553,7 @@ SQString *SQStringTable::Add(std::string_view new_string)
|
||||
}
|
||||
|
||||
SQString *t=(SQString *)SQ_MALLOC(len+sizeof(SQString));
|
||||
new (t) SQString(new_string);
|
||||
new (t, len+sizeof(SQString)) SQString(new_string);
|
||||
t->_next = _strings[slot];
|
||||
_strings[slot] = t;
|
||||
_slotused++;
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ public:
|
||||
static SQTable* Create(SQSharedState *ss,SQInteger nInitialSize)
|
||||
{
|
||||
SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable));
|
||||
new (newtable) SQTable(ss, nInitialSize);
|
||||
new (newtable, sizeof(SQTable)) SQTable(ss, nInitialSize);
|
||||
newtable->_delegate = nullptr;
|
||||
return newtable;
|
||||
}
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ struct SQUserData : SQDelegable
|
||||
static SQUserData* Create(SQSharedState *ss, SQInteger size)
|
||||
{
|
||||
SQUserData* ud = (SQUserData*)SQ_MALLOC(sizeof(SQUserData)+(size-1));
|
||||
new (ud) SQUserData(ss, size);
|
||||
new (ud, sizeof(SQUserData)+(size-1)) SQUserData(ss, size);
|
||||
return ud;
|
||||
}
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@
|
||||
|
||||
|
||||
/** Widgets for the configure AI window. */
|
||||
static constexpr NWidgetPart _nested_ai_config_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_ai_config_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
|
||||
NWidget(WWT_CAPTION, COLOUR_MAUVE), SetStringTip(STR_AI_CONFIG_CAPTION_AI, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
|
||||
@@ -137,5 +137,5 @@ AILibrary *AIScannerLibrary::FindLibrary(const std::string &library, int version
|
||||
ScriptInfoList::iterator it = this->info_list.find(library_name);
|
||||
if (it == this->info_list.end()) return nullptr;
|
||||
|
||||
return static_cast<AILibrary *>((*it).second);
|
||||
return static_cast<AILibrary *>(it->second);
|
||||
}
|
||||
|
||||
+27
-15
@@ -16,7 +16,6 @@
|
||||
#include "news_func.h"
|
||||
#include "newgrf_engine.h"
|
||||
#include "newgrf_sound.h"
|
||||
#include "spritecache.h"
|
||||
#include "error_func.h"
|
||||
#include "strings_func.h"
|
||||
#include "command_func.h"
|
||||
@@ -131,12 +130,14 @@ static StationID FindNearestHangar(const Aircraft *v)
|
||||
const Station *next_dest = nullptr;
|
||||
if (max_range != 0) {
|
||||
if (v->current_order.IsType(OT_GOTO_STATION) ||
|
||||
(v->current_order.IsType(OT_GOTO_DEPOT) && (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) == 0)) {
|
||||
(v->current_order.IsType(OT_GOTO_DEPOT) && !v->current_order.GetDepotActionType().Test(OrderDepotActionFlag::NearestDepot))) {
|
||||
last_dest = Station::GetIfValid(v->last_station_visited);
|
||||
next_dest = Station::GetIfValid(v->current_order.GetDestination().ToStationID());
|
||||
} else {
|
||||
last_dest = GetTargetAirportIfValid(v);
|
||||
next_dest = Station::GetIfValid(v->GetNextStoppingStation().value);
|
||||
std::vector<StationID> next_station;
|
||||
v->GetNextStoppingStation(next_station);
|
||||
if (!next_station.empty()) next_dest = Station::GetIfValid(next_station.back());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +201,7 @@ void GetRotorImage(const Aircraft *v, EngineImageType image_type, VehicleSpriteS
|
||||
static void GetAircraftIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
|
||||
{
|
||||
const Engine *e = Engine::Get(engine);
|
||||
uint8_t spritenum = e->u.air.image_index;
|
||||
uint8_t spritenum = e->VehInfo<AircraftVehicleInfo>().image_index;
|
||||
|
||||
if (IsCustomVehicleSpriteNum(spritenum)) {
|
||||
GetCustomVehicleIcon(engine, DIR_W, image_type, result);
|
||||
@@ -267,7 +268,7 @@ void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoff
|
||||
*/
|
||||
CommandCost CmdBuildAircraft(DoCommandFlags flags, TileIndex tile, const Engine *e, Vehicle **ret)
|
||||
{
|
||||
const AircraftVehicleInfo *avi = &e->u.air;
|
||||
const AircraftVehicleInfo *avi = &e->VehInfo<AircraftVehicleInfo>();
|
||||
const Station *st = Station::GetByTile(tile);
|
||||
|
||||
/* Prevent building aircraft types at places which can't handle them */
|
||||
@@ -427,7 +428,7 @@ static void CheckIfAircraftNeedsService(Aircraft *v)
|
||||
|
||||
/* only goto depot if the target airport has a depot */
|
||||
if (st->airport.HasHangar() && CanVehicleUseStation(v, st)) {
|
||||
v->current_order.MakeGoToDepot(st->index, ODTFB_SERVICE);
|
||||
v->current_order.MakeGoToDepot(st->index, OrderDepotTypeFlag::Service);
|
||||
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
|
||||
} else if (v->current_order.IsType(OT_GOTO_DEPOT)) {
|
||||
v->current_order.MakeDummy();
|
||||
@@ -438,7 +439,7 @@ static void CheckIfAircraftNeedsService(Aircraft *v)
|
||||
Money Aircraft::GetRunningCost() const
|
||||
{
|
||||
const Engine *e = this->GetEngine();
|
||||
uint cost_factor = GetVehicleProperty(this, PROP_AIRCRAFT_RUNNING_COST_FACTOR, e->u.air.running_cost);
|
||||
uint cost_factor = GetVehicleProperty(this, PROP_AIRCRAFT_RUNNING_COST_FACTOR, e->VehInfo<AircraftVehicleInfo>().running_cost);
|
||||
return GetPrice(PR_RUNNING_AIRCRAFT, cost_factor, e->GetGRF());
|
||||
}
|
||||
|
||||
@@ -987,7 +988,7 @@ static bool AircraftController(Aircraft *v)
|
||||
}
|
||||
|
||||
/* Get distance from destination pos to current pos. */
|
||||
uint dist = abs(x + amd.x - v->x_pos) + abs(y + amd.y - v->y_pos);
|
||||
uint dist = abs(x + amd.x - v->x_pos) + abs(y + amd.y - v->y_pos);
|
||||
|
||||
/* Need exact position? */
|
||||
if (!amd.flags.Test(AirportMovingDataFlag::ExactPosition) && dist <= (amd.flags.Test(AirportMovingDataFlag::SlowTurn) ? 8U : 4U)) return true;
|
||||
@@ -1020,10 +1021,21 @@ static bool AircraftController(Aircraft *v)
|
||||
uint speed_limit = SPEED_LIMIT_TAXI;
|
||||
bool hard_limit = true;
|
||||
|
||||
if (amd.flags.Test(AirportMovingDataFlag::NoSpeedClamp)) speed_limit = SPEED_LIMIT_NONE;
|
||||
if (amd.flags.Test(AirportMovingDataFlag::Hold)) { speed_limit = SPEED_LIMIT_HOLD; hard_limit = false; }
|
||||
if (amd.flags.Test(AirportMovingDataFlag::Land)) { speed_limit = SPEED_LIMIT_APPROACH; hard_limit = false; }
|
||||
if (amd.flags.Test(AirportMovingDataFlag::Brake)) { speed_limit = SPEED_LIMIT_TAXI; hard_limit = false; }
|
||||
if (amd.flags.Test(AirportMovingDataFlag::NoSpeedClamp)) {
|
||||
speed_limit = SPEED_LIMIT_NONE;
|
||||
}
|
||||
if (amd.flags.Test(AirportMovingDataFlag::Hold)) {
|
||||
speed_limit = SPEED_LIMIT_HOLD;
|
||||
hard_limit = false;
|
||||
}
|
||||
if (amd.flags.Test(AirportMovingDataFlag::Land)) {
|
||||
speed_limit = SPEED_LIMIT_APPROACH;
|
||||
hard_limit = false;
|
||||
}
|
||||
if (amd.flags.Test(AirportMovingDataFlag::Brake)) {
|
||||
speed_limit = SPEED_LIMIT_TAXI;
|
||||
hard_limit = false;
|
||||
}
|
||||
|
||||
int count = UpdateAircraftSpeed(v, speed_limit, hard_limit);
|
||||
if (count == 0) return false;
|
||||
@@ -1180,7 +1192,7 @@ static bool HandleCrashedAircraft(Aircraft *v)
|
||||
Station *st = GetTargetAirportIfValid(v);
|
||||
|
||||
/* make aircraft crash down to the ground */
|
||||
if (v->crashed_counter < 500 && st == nullptr && ((v->crashed_counter % 3) == 0) ) {
|
||||
if (v->crashed_counter < 500 && st == nullptr && ((v->crashed_counter % 3) == 0)) {
|
||||
int z = GetSlopePixelZ(Clamp(v->x_pos, 0, Map::MaxX() * TILE_SIZE), Clamp(v->y_pos, 0, Map::MaxY() * TILE_SIZE));
|
||||
v->z_pos -= 1;
|
||||
if (v->z_pos <= z) {
|
||||
@@ -1813,7 +1825,7 @@ static bool AirportMove(Aircraft *v, const AirportFTAClass *apc)
|
||||
{
|
||||
/* error handling */
|
||||
if (v->pos >= apc->nofelements) {
|
||||
Debug(misc, 0, "[Ap] position {} is not valid for current airport. Max position is {}", v->pos, apc->nofelements-1);
|
||||
Debug(misc, 0, "[Ap] position {} is not valid for current airport. Max position is {}", v->pos, apc->nofelements - 1);
|
||||
assert(v->pos < apc->nofelements);
|
||||
}
|
||||
|
||||
@@ -2175,7 +2187,7 @@ void UpdateAirplanesOnNewStation(const Station *st)
|
||||
Order *o = &v->current_order;
|
||||
/* The aircraft is heading to a hangar, but the new station doesn't have one,
|
||||
* or the aircraft can't land on the new station. Cancel current order. */
|
||||
if (o->IsType(OT_GOTO_DEPOT) && !(o->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) && o->GetDestination() == st->index &&
|
||||
if (o->IsType(OT_GOTO_DEPOT) && !o->GetDepotOrderType().Test(OrderDepotTypeFlag::PartOfOrders) && o->GetDestination() == st->index &&
|
||||
(!st->airport.HasHangar() || !CanVehicleUseStation(v, st))) {
|
||||
o->MakeDummy();
|
||||
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "strings_func.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "window_gui.h"
|
||||
#include "spritecache.h"
|
||||
#include "zoom_func.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
+9
-4
@@ -84,7 +84,7 @@ static void PlaceAirport(TileIndex tile)
|
||||
|
||||
/** Airport build toolbar window handler. */
|
||||
struct BuildAirToolbarWindow : Window {
|
||||
int last_user_action = INVALID_WID_AT; // Last started user action.
|
||||
WidgetID last_user_action = INVALID_WIDGET; // Last started user action.
|
||||
|
||||
BuildAirToolbarWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc)
|
||||
{
|
||||
@@ -161,6 +161,11 @@ struct BuildAirToolbarWindow : Window {
|
||||
VpSelectTilesWithMethod(pt.x, pt.y, select_method);
|
||||
}
|
||||
|
||||
Point OnInitialPosition(int16_t sm_width, [[maybe_unused]] int16_t sm_height, [[maybe_unused]] int window_number) override
|
||||
{
|
||||
return AlignInitialConstructionToolbar(sm_width);
|
||||
}
|
||||
|
||||
void OnPlaceMouseUp([[maybe_unused]] ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, [[maybe_unused]] Point pt, TileIndex start_tile, TileIndex end_tile) override
|
||||
{
|
||||
if (pt.x != -1 && select_proc == DDSP_DEMOLISH_AREA) {
|
||||
@@ -197,7 +202,7 @@ struct BuildAirToolbarWindow : Window {
|
||||
}, AirportToolbarGlobalHotkeys};
|
||||
};
|
||||
|
||||
static constexpr NWidgetPart _nested_air_toolbar_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_air_toolbar_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_TOOLBAR_AIRCRAFT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
@@ -211,7 +216,7 @@ static constexpr NWidgetPart _nested_air_toolbar_widgets[] = {
|
||||
};
|
||||
|
||||
static WindowDesc _air_toolbar_desc(
|
||||
WDP_ALIGN_TOOLBAR, "toolbar_air", 0, 0,
|
||||
WDP_MANUAL, "toolbar_air", 0, 0,
|
||||
WC_BUILD_TOOLBAR, WC_NONE,
|
||||
WindowDefaultFlag::Construction,
|
||||
_nested_air_toolbar_widgets,
|
||||
@@ -580,7 +585,7 @@ public:
|
||||
}};
|
||||
};
|
||||
|
||||
static constexpr NWidgetPart _nested_build_airport_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_build_airport_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_STATION_BUILD_AIRPORT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
|
||||
@@ -363,12 +363,12 @@ void AddArticulatedParts(Vehicle *first)
|
||||
|
||||
t->subtype = 0;
|
||||
t->track = front->track;
|
||||
t->railtype = front->railtype;
|
||||
t->railtypes = front->railtypes;
|
||||
|
||||
t->spritenum = e_artic->u.rail.image_index;
|
||||
t->spritenum = e_artic->VehInfo<RailVehicleInfo>().image_index;
|
||||
if (e_artic->CanCarryCargo()) {
|
||||
t->cargo_type = e_artic->GetDefaultCargoType();
|
||||
t->cargo_cap = e_artic->u.rail.capacity; // Callback 36 is called when the consist is finished
|
||||
t->cargo_cap = e_artic->VehInfo<RailVehicleInfo>().capacity; // Callback 36 is called when the consist is finished
|
||||
} else {
|
||||
t->cargo_type = front->cargo_type; // Needed for livery selection
|
||||
t->cargo_cap = 0;
|
||||
@@ -392,11 +392,11 @@ void AddArticulatedParts(Vehicle *first)
|
||||
rv->roadtype = front->roadtype;
|
||||
rv->compatible_roadtypes = front->compatible_roadtypes;
|
||||
|
||||
rv->spritenum = e_artic->u.road.image_index;
|
||||
rv->spritenum = e_artic->VehInfo<RoadVehicleInfo>().image_index;
|
||||
if (e_artic->CanCarryCargo()) {
|
||||
rv->cargo_type = e_artic->GetDefaultCargoType();
|
||||
assert(IsValidCargoType(rv->cargo_type));
|
||||
rv->cargo_cap = e_artic->u.road.capacity; // Callback 36 is called when the consist is finished
|
||||
rv->cargo_cap = e_artic->VehInfo<RoadVehicleInfo>().capacity; // Callback 36 is called when the consist is finished
|
||||
} else {
|
||||
rv->cargo_type = front->cargo_type; // Needed for livery selection
|
||||
rv->cargo_cap = 0;
|
||||
|
||||
@@ -71,16 +71,16 @@ bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company)
|
||||
switch (type) {
|
||||
case VEH_TRAIN: {
|
||||
/* make sure the railtypes are compatible */
|
||||
if (!GetRailTypeInfo(e_from->u.rail.railtype)->compatible_railtypes.Any(GetRailTypeInfo(e_to->u.rail.railtype)->compatible_railtypes)) return false;
|
||||
if (!GetAllCompatibleRailTypes(e_from->VehInfo<RailVehicleInfo>().railtypes).Any(GetAllCompatibleRailTypes(e_to->VehInfo<RailVehicleInfo>().railtypes))) return false;
|
||||
|
||||
/* make sure we do not replace wagons with engines or vice versa */
|
||||
if ((e_from->u.rail.railveh_type == RAILVEH_WAGON) != (e_to->u.rail.railveh_type == RAILVEH_WAGON)) return false;
|
||||
if ((e_from->VehInfo<RailVehicleInfo>().railveh_type == RAILVEH_WAGON) != (e_to->VehInfo<RailVehicleInfo>().railveh_type == RAILVEH_WAGON)) return false;
|
||||
break;
|
||||
}
|
||||
|
||||
case VEH_ROAD:
|
||||
/* make sure the roadtypes are compatible */
|
||||
if (!GetRoadTypeInfo(e_from->u.road.roadtype)->powered_roadtypes.Any(GetRoadTypeInfo(e_to->u.road.roadtype)->powered_roadtypes)) return false;
|
||||
if (!GetRoadTypeInfo(e_from->VehInfo<RoadVehicleInfo>().roadtype)->powered_roadtypes.Any(GetRoadTypeInfo(e_to->VehInfo<RoadVehicleInfo>().roadtype)->powered_roadtypes)) return false;
|
||||
|
||||
/* make sure that we do not replace a tram with a normal road vehicles or vice versa */
|
||||
if (e_from->info.misc_flags.Test(EngineMiscFlag::RoadIsTram) != e_to->info.misc_flags.Test(EngineMiscFlag::RoadIsTram)) return false;
|
||||
@@ -88,7 +88,7 @@ bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company)
|
||||
|
||||
case VEH_AIRCRAFT:
|
||||
/* make sure that we do not replace a plane with a helicopter or vice versa */
|
||||
if ((e_from->u.air.subtype & AIR_CTOL) != (e_to->u.air.subtype & AIR_CTOL)) return false;
|
||||
if ((e_from->VehInfo<AircraftVehicleInfo>().subtype & AIR_CTOL) != (e_to->VehInfo<AircraftVehicleInfo>().subtype & AIR_CTOL)) return false;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
CommandCost CmdAutoreplaceVehicle(DoCommandFlags flags, VehicleID veh_id);
|
||||
CommandCost CmdSetAutoReplace(DoCommandFlags flags, GroupID id_g, EngineID old_engine_type, EngineID new_engine_type, bool when_old);
|
||||
|
||||
DEF_CMD_TRAIT(CMD_AUTOREPLACE_VEHICLE, CmdAutoreplaceVehicle, {}, CMDT_VEHICLE_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_SET_AUTOREPLACE, CmdSetAutoReplace, {}, CMDT_VEHICLE_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_AUTOREPLACE_VEHICLE, CmdAutoreplaceVehicle, {}, CommandType::VehicleManagement)
|
||||
DEF_CMD_TRAIT(CMD_SET_AUTOREPLACE, CmdSetAutoReplace, {}, CommandType::VehicleManagement)
|
||||
|
||||
#endif /* AUTOREPLACE_CMD_H */
|
||||
|
||||
@@ -111,7 +111,7 @@ class ReplaceVehicleWindow : public Window {
|
||||
|
||||
if (draw_left && this->sel_railtype != INVALID_RAILTYPE) {
|
||||
/* Ensure that the railtype is specific to the selected one */
|
||||
if (rvi->railtype != this->sel_railtype) return false;
|
||||
if (!rvi->railtypes.Test(this->sel_railtype)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -140,7 +140,7 @@ class ReplaceVehicleWindow : public Window {
|
||||
case VEH_ROAD:
|
||||
if (draw_left && this->sel_roadtype != INVALID_ROADTYPE) {
|
||||
/* Ensure that the roadtype is specific to the selected one */
|
||||
if (e->u.road.roadtype != this->sel_roadtype) continue;
|
||||
if (e->VehInfo<RoadVehicleInfo>().roadtype != this->sel_roadtype) continue;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -698,7 +698,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr NWidgetPart _nested_replace_rail_vehicle_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_replace_rail_vehicle_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION),
|
||||
@@ -762,7 +762,7 @@ static WindowDesc _replace_rail_vehicle_desc(
|
||||
_nested_replace_rail_vehicle_widgets
|
||||
);
|
||||
|
||||
static constexpr NWidgetPart _nested_replace_road_vehicle_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_replace_road_vehicle_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION),
|
||||
@@ -820,7 +820,7 @@ static WindowDesc _replace_road_vehicle_desc(
|
||||
_nested_replace_road_vehicle_widgets
|
||||
);
|
||||
|
||||
static constexpr NWidgetPart _nested_replace_vehicle_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_replace_vehicle_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION), SetMinimalSize(433, 14),
|
||||
|
||||
@@ -79,7 +79,7 @@ bool BaseSet<T>::FillSetDetails(const IniFile &ini, const std::string &path, con
|
||||
|
||||
/* Add the translations of the descriptions too. */
|
||||
for (const IniItem &titem : metadata->items) {
|
||||
if (titem.name.compare(0, 12, "description.") != 0) continue;
|
||||
if (!titem.name.starts_with("description.")) continue;
|
||||
|
||||
this->description[titem.name.substr(12)] = titem.value.value_or("");
|
||||
}
|
||||
|
||||
@@ -33,14 +33,14 @@ enum MusicTrackType : uint8_t {
|
||||
|
||||
/** Metadata about a music track. */
|
||||
struct MusicSongInfo {
|
||||
std::string songname; ///< name of song displayed in UI
|
||||
uint8_t tracknr; ///< track number of song displayed in UI
|
||||
std::string filename; ///< file on disk containing song (when used in MusicSet class)
|
||||
std::string songname; ///< name of song displayed in UI
|
||||
std::string filename; ///< file on disk containing song (when used in MusicSet class)
|
||||
int cat_index; ///< entry index in CAT file, for filetype==MTT_MPSMIDI
|
||||
int override_start; ///< MIDI ticks to skip over in beginning
|
||||
int override_end; ///< MIDI tick to end the song at (0 if no override)
|
||||
uint8_t tracknr; ///< track number of song displayed in UI
|
||||
MusicTrackType filetype; ///< decoder required for song file
|
||||
int cat_index; ///< entry index in CAT file, for filetype==MTT_MPSMIDI
|
||||
bool loop; ///< song should play in a tight loop if possible, never ending
|
||||
int override_start; ///< MIDI ticks to skip over in beginning
|
||||
int override_end; ///< MIDI tick to end the song at (0 if no override)
|
||||
bool loop; ///< song should play in a tight loop if possible, never ending
|
||||
};
|
||||
|
||||
template <> struct BaseSetTraits<struct MusicSet> {
|
||||
|
||||
+2
-2
@@ -118,9 +118,9 @@ public:
|
||||
|
||||
inline TileIterator& operator ++() override
|
||||
{
|
||||
(*this).OrthogonalTileIterator::operator++();
|
||||
this->OrthogonalTileIterator::operator++();
|
||||
while (this->tile != INVALID_TILE && !this->bitmap->HasTile(TileIndex(this->tile))) {
|
||||
(*this).OrthogonalTileIterator::operator++();
|
||||
this->OrthogonalTileIterator::operator++();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ Sprite *Blitter_32bppSSE_Base::Encode(SpriteType sprite_type, const SpriteLoader
|
||||
else break;
|
||||
dst_rgba++;
|
||||
}
|
||||
(*dst_rgba_line).data = nb_pix_transp;
|
||||
dst_rgba_line->data = nb_pix_transp;
|
||||
|
||||
Colour *nb_right = dst_rgba_line + 1;
|
||||
dst_rgba_line = reinterpret_cast<Colour *>(reinterpret_cast<std::byte *>(dst_rgba_line) + info.sprite_line_size);
|
||||
@@ -126,7 +126,7 @@ Sprite *Blitter_32bppSSE_Base::Encode(SpriteType sprite_type, const SpriteLoader
|
||||
else break;
|
||||
dst_rgba--;
|
||||
}
|
||||
(*nb_right).data = nb_pix_transp;
|
||||
nb_right->data = nb_pix_transp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -240,9 +240,9 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
||||
if (src_px->a == 255) {
|
||||
src_px += n;
|
||||
do {
|
||||
/* If the anim buffer contains a color value, the image composition will
|
||||
/* If the anim buffer contains a colour value, the image composition will
|
||||
* only look at the RGB brightness value. As such, we can simply darken the
|
||||
* RGB value to darken the anim color. */
|
||||
* RGB value to darken the anim colour. */
|
||||
Colour b = *anim != 0 ? Colour(GetColourBrightness(*dst), 0, 0) : *dst;
|
||||
*dst = this->MakeTransparent(b, 3, 4);
|
||||
anim++;
|
||||
@@ -360,9 +360,9 @@ void Blitter_40bppAnim::DrawColourMappingRect(void *dst, int width, int height,
|
||||
uint8_t *anim = VideoDriver::GetInstance()->GetAnimBuffer() + ((uint32_t *)dst - (uint32_t *)_screen.dst_ptr);
|
||||
|
||||
if (pal == PALETTE_TO_TRANSPARENT) {
|
||||
/* If the anim buffer contains a color value, the image composition will
|
||||
/* If the anim buffer contains a colour value, the image composition will
|
||||
* only look at the RGB brightness value. As such, we can simply darken the
|
||||
* RGB value to darken the anim color. */
|
||||
* RGB value to darken the anim colour. */
|
||||
do {
|
||||
for (int i = 0; i != width; i++) {
|
||||
Colour b = *anim != 0 ? Colour(GetColourBrightness(*udst), 0, 0) : *udst;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "safeguards.h"
|
||||
|
||||
/** Widgets for the background window to prevent smearing. */
|
||||
static constexpr NWidgetPart _background_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _background_widgets = {
|
||||
NWidget(WWT_PANEL, COLOUR_DARK_BLUE, WID_BB_BACKGROUND), SetResize(1, 1),
|
||||
EndContainer(),
|
||||
};
|
||||
@@ -60,13 +60,13 @@ public:
|
||||
|
||||
void DrawWidget(const Rect &r, WidgetID) const override
|
||||
{
|
||||
GfxFillRect(r.left, r.top, r.right, r.bottom, PixelColour{4}, FILLRECT_OPAQUE);
|
||||
GfxFillRect(r.left, r.top, r.right, r.bottom, PixelColour{0}, FILLRECT_CHECKER);
|
||||
GfxFillRect(r, PixelColour{4}, FILLRECT_OPAQUE);
|
||||
GfxFillRect(r, PixelColour{0}, FILLRECT_CHECKER);
|
||||
}
|
||||
};
|
||||
|
||||
/** Nested widgets for the error window. */
|
||||
static constexpr NWidgetPart _nested_bootstrap_errmsg_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_bootstrap_errmsg_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_BEM_CAPTION), SetStringTip(STR_MISSING_GRAPHICS_ERROR_TITLE),
|
||||
EndContainer(),
|
||||
@@ -123,7 +123,7 @@ public:
|
||||
};
|
||||
|
||||
/** Nested widgets for the download window. */
|
||||
static constexpr NWidgetPart _nested_bootstrap_download_status_window_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_bootstrap_download_status_window_widgets = {
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_CONTENT_DOWNLOAD_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY),
|
||||
NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), SetPadding(WidgetDimensions::unscaled.modalpopup),
|
||||
@@ -174,7 +174,7 @@ public:
|
||||
};
|
||||
|
||||
/** The widgets for the query. It has no close box as that sprite does not exist yet. */
|
||||
static constexpr NWidgetPart _bootstrap_query_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _bootstrap_query_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_MISSING_GRAPHICS_SET_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
EndContainer(),
|
||||
@@ -380,7 +380,7 @@ bool HandleBootstrap()
|
||||
/* Initialise the font cache. */
|
||||
InitializeUnicodeGlyphMap();
|
||||
/* Next "force" finding a suitable non-sprite font as the local font is missing. */
|
||||
CheckForMissingGlyphs(false);
|
||||
CheckForMissingGlyphs();
|
||||
|
||||
/* Initialise the palette. The biggest step is 'faking' some recolour sprites.
|
||||
* This way the mauve and gray colours work and we can show the user interface. */
|
||||
|
||||
+1
-1
@@ -309,7 +309,7 @@ const std::initializer_list<GUIBridgeList::SortFunction * const> BuildBridgeWind
|
||||
};
|
||||
|
||||
/** Widgets of the bridge gui. */
|
||||
static constexpr NWidgetPart _nested_build_bridge_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_build_bridge_widgets = {
|
||||
/* Header */
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||
|
||||
@@ -135,6 +135,7 @@ inline void MakeBridgeRamp(Tile t, Owner o, BridgeType bridgetype, DiagDirection
|
||||
t.m4() = 0;
|
||||
t.m5() = 1 << 7 | tt << 2 | d;
|
||||
SB(t.m6(), 2, 4, bridgetype);
|
||||
SB(t.m6(), 6, 2, 0);
|
||||
t.m7() = 0;
|
||||
t.m8() = 0;
|
||||
}
|
||||
|
||||
+45
-22
@@ -58,7 +58,7 @@ uint GetEngineListHeight(VehicleType type)
|
||||
return std::max<uint>(GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.matrix.Vertical(), GetVehicleImageCellSize(type, EIT_PURCHASE).height);
|
||||
}
|
||||
|
||||
static constexpr NWidgetPart _nested_build_vehicle_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_build_vehicle_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_BV_CAPTION), SetTextStyle(TC_WHITE),
|
||||
@@ -632,14 +632,33 @@ static int DrawRailEnginePurchaseInfo(int left, int right, int y, EngineID engin
|
||||
}
|
||||
y += GetCharacterHeight(FS_NORMAL);
|
||||
|
||||
/* Supported rail types */
|
||||
std::string railtypes{};
|
||||
std::string_view list_separator = GetListSeparator();
|
||||
|
||||
for (const auto &rt : _sorted_railtypes) {
|
||||
if (!rvi->railtypes.Test(rt)) continue;
|
||||
|
||||
if (!railtypes.empty()) railtypes += list_separator;
|
||||
AppendStringInPlace(railtypes, GetRailTypeInfo(rt)->strings.name);
|
||||
}
|
||||
DrawString(left, right, y, GetString(STR_PURCHASE_INFO_RAILTYPES, railtypes));
|
||||
y += GetCharacterHeight(FS_NORMAL);
|
||||
|
||||
/* Max speed - Engine power */
|
||||
DrawString(left, right, y, GetString(STR_PURCHASE_INFO_SPEED_POWER, PackVelocity(e->GetDisplayMaxSpeed(), e->type), e->GetPower()));
|
||||
y += GetCharacterHeight(FS_NORMAL);
|
||||
|
||||
/* Max tractive effort - not applicable if old acceleration or maglev */
|
||||
if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL && GetRailTypeInfo(rvi->railtype)->acceleration_type != 2) {
|
||||
DrawString(left, right, y, GetString(STR_PURCHASE_INFO_MAX_TE, e->GetDisplayMaxTractiveEffort()));
|
||||
y += GetCharacterHeight(FS_NORMAL);
|
||||
if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL) {
|
||||
bool is_maglev = true;
|
||||
for (RailType rt : rvi->railtypes) {
|
||||
is_maglev &= GetRailTypeInfo(rt)->acceleration_type == VehicleAccelerationModel::Maglev;
|
||||
}
|
||||
if (!is_maglev) {
|
||||
DrawString(left, right, y, GetString(STR_PURCHASE_INFO_MAX_TE, e->GetDisplayMaxTractiveEffort()));
|
||||
y += GetCharacterHeight(FS_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Running cost */
|
||||
@@ -707,8 +726,8 @@ static int DrawShipPurchaseInfo(int left, int right, int y, EngineID engine_numb
|
||||
|
||||
/* Purchase cost - Max speed */
|
||||
uint raw_speed = e->GetDisplayMaxSpeed();
|
||||
uint ocean_speed = e->u.ship.ApplyWaterClassSpeedFrac(raw_speed, true);
|
||||
uint canal_speed = e->u.ship.ApplyWaterClassSpeedFrac(raw_speed, false);
|
||||
uint ocean_speed = e->VehInfo<ShipVehicleInfo>().ApplyWaterClassSpeedFrac(raw_speed, true);
|
||||
uint canal_speed = e->VehInfo<ShipVehicleInfo>().ApplyWaterClassSpeedFrac(raw_speed, false);
|
||||
|
||||
if (ocean_speed == canal_speed) {
|
||||
if (te.cost != 0) {
|
||||
@@ -866,10 +885,10 @@ int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number,
|
||||
switch (e->type) {
|
||||
default: NOT_REACHED();
|
||||
case VEH_TRAIN:
|
||||
if (e->u.rail.railveh_type == RAILVEH_WAGON) {
|
||||
y = DrawRailWagonPurchaseInfo(left, right, y, engine_number, &e->u.rail, te);
|
||||
if (e->VehInfo<RailVehicleInfo>().railveh_type == RAILVEH_WAGON) {
|
||||
y = DrawRailWagonPurchaseInfo(left, right, y, engine_number, &e->VehInfo<RailVehicleInfo>(), te);
|
||||
} else {
|
||||
y = DrawRailEnginePurchaseInfo(left, right, y, engine_number, &e->u.rail, te);
|
||||
y = DrawRailEnginePurchaseInfo(left, right, y, engine_number, &e->VehInfo<RailVehicleInfo>(), te);
|
||||
}
|
||||
articulated_cargo = true;
|
||||
break;
|
||||
@@ -901,7 +920,7 @@ int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number,
|
||||
}
|
||||
|
||||
/* Draw details that apply to all types except rail wagons. */
|
||||
if (e->type != VEH_TRAIN || e->u.rail.railveh_type != RAILVEH_WAGON) {
|
||||
if (e->type != VEH_TRAIN || e->VehInfo<RailVehicleInfo>().railveh_type != RAILVEH_WAGON) {
|
||||
/* Design date - Life length */
|
||||
DrawString(left, right, y, GetString(STR_PURCHASE_INFO_DESIGNED_LIFE, ymd.year, TimerGameCalendar::DateToYear(e->GetLifeLengthInDays())));
|
||||
y += GetCharacterHeight(FS_NORMAL);
|
||||
@@ -1011,7 +1030,7 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
|
||||
|
||||
if (has_variants) {
|
||||
Rect fr = tr.WithWidth(circle_width, rtl);
|
||||
DrawSpriteIgnorePadding(is_folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED, PAL_NONE, {fr.left, textr.top, fr.right, textr.bottom}, SA_CENTER);
|
||||
DrawSpriteIgnorePadding(is_folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED, PAL_NONE, fr.WithY(textr), SA_CENTER);
|
||||
}
|
||||
|
||||
tr = tr.Indent(circle_width + WidgetDimensions::scaled.hsep_normal, rtl);
|
||||
@@ -1315,8 +1334,7 @@ struct BuildVehicleWindow : Window {
|
||||
this->badge_classes = GUIBadgeClasses(static_cast<GrfSpecFeature>(GSF_TRAINS + this->vehicle_type));
|
||||
this->SetCargoFilterArray();
|
||||
|
||||
auto container = this->GetWidget<NWidgetContainer>(WID_BV_BADGE_FILTER);
|
||||
this->badge_filters = AddBadgeDropdownFilters(*container, WID_BV_BADGE_FILTER, COLOUR_GREY, static_cast<GrfSpecFeature>(GSF_TRAINS + this->vehicle_type));
|
||||
this->badge_filters = AddBadgeDropdownFilters(this, WID_BV_BADGE_FILTER, WID_BV_BADGE_FILTER, COLOUR_GREY, static_cast<GrfSpecFeature>(GSF_TRAINS + this->vehicle_type));
|
||||
|
||||
this->widget_lookup.clear();
|
||||
this->nested_root->FillWidgetLookup(this->widget_lookup);
|
||||
@@ -1376,9 +1394,9 @@ struct BuildVehicleWindow : Window {
|
||||
for (const Engine *e : Engine::IterateType(VEH_TRAIN)) {
|
||||
if (!this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue;
|
||||
EngineID eid = e->index;
|
||||
const RailVehicleInfo *rvi = &e->u.rail;
|
||||
const RailVehicleInfo *rvi = &e->VehInfo<RailVehicleInfo>();
|
||||
|
||||
if (this->filter.railtype != INVALID_RAILTYPE && !HasPowerOnRail(rvi->railtype, this->filter.railtype)) continue;
|
||||
if (this->filter.railtype != INVALID_RAILTYPE && !HasPowerOnRail(rvi->railtypes, this->filter.railtype)) continue;
|
||||
if (!IsEngineBuildable(eid, VEH_TRAIN, _local_company)) continue;
|
||||
|
||||
/* Filter now! So num_engines and num_wagons is valid */
|
||||
@@ -1407,7 +1425,7 @@ struct BuildVehicleWindow : Window {
|
||||
if (std::ranges::find(list, variant, &GUIEngineListItem::engine_id) == list.end()) {
|
||||
const Engine *e = Engine::Get(variant);
|
||||
list.emplace_back(variant, e->info.variant_id, e->display_flags | EngineDisplayFlag::Shaded, 0);
|
||||
if (e->u.rail.railveh_type != RAILVEH_WAGON) num_engines++;
|
||||
if (e->VehInfo<RailVehicleInfo>().railveh_type != RAILVEH_WAGON) num_engines++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1436,12 +1454,14 @@ struct BuildVehicleWindow : Window {
|
||||
this->eng_list.clear();
|
||||
|
||||
BadgeTextFilter btf(this->string_filter, GSF_ROADVEHICLES);
|
||||
BadgeDropdownFilter bdf(this->badge_filter_choices);
|
||||
|
||||
for (const Engine *e : Engine::IterateType(VEH_ROAD)) {
|
||||
if (!this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue;
|
||||
EngineID eid = e->index;
|
||||
if (!IsEngineBuildable(eid, VEH_ROAD, _local_company)) continue;
|
||||
if (this->filter.roadtype != INVALID_ROADTYPE && !HasPowerOnRoad(e->u.road.roadtype, this->filter.roadtype)) continue;
|
||||
if (this->filter.roadtype != INVALID_ROADTYPE && !HasPowerOnRoad(e->VehInfo<RoadVehicleInfo>().roadtype, this->filter.roadtype)) continue;
|
||||
if (!bdf.Filter(e->badges)) continue;
|
||||
|
||||
/* Filter by name or NewGRF extra text */
|
||||
if (!FilterByText(e) && !btf.Filter(e->badges)) continue;
|
||||
@@ -1460,11 +1480,13 @@ struct BuildVehicleWindow : Window {
|
||||
this->eng_list.clear();
|
||||
|
||||
BadgeTextFilter btf(this->string_filter, GSF_SHIPS);
|
||||
BadgeDropdownFilter bdf(this->badge_filter_choices);
|
||||
|
||||
for (const Engine *e : Engine::IterateType(VEH_SHIP)) {
|
||||
if (!this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue;
|
||||
EngineID eid = e->index;
|
||||
if (!IsEngineBuildable(eid, VEH_SHIP, _local_company)) continue;
|
||||
if (!bdf.Filter(e->badges)) continue;
|
||||
|
||||
/* Filter by name or NewGRF extra text */
|
||||
if (!FilterByText(e) && !btf.Filter(e->badges)) continue;
|
||||
@@ -1486,6 +1508,7 @@ struct BuildVehicleWindow : Window {
|
||||
const Station *st = this->listview_mode ? nullptr : Station::GetByTile(TileIndex(this->window_number));
|
||||
|
||||
BadgeTextFilter btf(this->string_filter, GSF_AIRCRAFT);
|
||||
BadgeDropdownFilter bdf(this->badge_filter_choices);
|
||||
|
||||
/* Make list of all available planes.
|
||||
* Also check to see if the previously selected plane is still available,
|
||||
@@ -1497,6 +1520,7 @@ struct BuildVehicleWindow : Window {
|
||||
if (!IsEngineBuildable(eid, VEH_AIRCRAFT, _local_company)) continue;
|
||||
/* First VEH_END window_numbers are fake to allow a window open for all different types at once */
|
||||
if (!this->listview_mode && !CanVehicleUseStation(eid, st)) continue;
|
||||
if (!bdf.Filter(e->badges)) continue;
|
||||
|
||||
/* Filter by name or NewGRF extra text */
|
||||
if (!FilterByText(e) && !btf.Filter(e->badges)) continue;
|
||||
@@ -1592,7 +1616,7 @@ struct BuildVehicleWindow : Window {
|
||||
DropDownList BuildBadgeConfigurationList() const
|
||||
{
|
||||
static const auto separators = {STR_BADGE_CONFIG_PREVIEW, STR_BADGE_CONFIG_NAME};
|
||||
return BuildBadgeClassConfigurationList(this->badge_classes, BADGE_COLUMNS, separators);
|
||||
return BuildBadgeClassConfigurationList(this->badge_classes, BADGE_COLUMNS, separators, COLOUR_GREY);
|
||||
}
|
||||
|
||||
void BuildVehicle()
|
||||
@@ -1680,7 +1704,7 @@ struct BuildVehicleWindow : Window {
|
||||
|
||||
case WID_BV_CONFIGURE_BADGES:
|
||||
if (this->badge_classes.GetClasses().empty()) break;
|
||||
ShowDropDownList(this, this->BuildBadgeConfigurationList(), -1, widget, 0, false, true);
|
||||
ShowDropDownList(this, this->BuildBadgeConfigurationList(), -1, widget, 0, DropDownOption::Persist);
|
||||
break;
|
||||
|
||||
case WID_BV_SHOW_HIDE: {
|
||||
@@ -1706,7 +1730,8 @@ struct BuildVehicleWindow : Window {
|
||||
|
||||
default:
|
||||
if (IsInsideMM(widget, this->badge_filters.first, this->badge_filters.second)) {
|
||||
ShowDropDownList(this, this->GetWidget<NWidgetBadgeFilter>(widget)->GetDropDownList(), -1, widget, 0, false);
|
||||
PaletteID palette = SPR_2CCMAP_BASE + Company::Get(_local_company)->GetCompanyRecolourOffset(LS_DEFAULT);
|
||||
ShowDropDownList(this, this->GetWidget<NWidgetBadgeFilter>(widget)->GetDropDownList(palette), -1, widget, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1906,7 +1931,6 @@ struct BuildVehicleWindow : Window {
|
||||
|
||||
/* We need to refresh if a filter is removed. */
|
||||
this->eng_list.ForceRebuild();
|
||||
this->SetDirty();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1918,7 +1942,6 @@ struct BuildVehicleWindow : Window {
|
||||
SetBadgeFilter(this->badge_filter_choices, BadgeID(index));
|
||||
}
|
||||
this->eng_list.ForceRebuild();
|
||||
this->SetDirty();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
+17
-17
@@ -404,13 +404,13 @@ void VehicleCargoList::AgeCargo()
|
||||
* @return MoveToAction to be performed.
|
||||
*/
|
||||
/* static */ VehicleCargoList::MoveToAction VehicleCargoList::ChooseAction(const CargoPacket *cp, StationID cargo_next,
|
||||
StationID current_station, bool accepted, StationIDStack next_station)
|
||||
StationID current_station, bool accepted, std::span<const StationID> next_station)
|
||||
{
|
||||
if (cargo_next == StationID::Invalid()) {
|
||||
return (accepted && cp->first_station != current_station) ? MTA_DELIVER : MTA_KEEP;
|
||||
} else if (cargo_next == current_station) {
|
||||
return MTA_DELIVER;
|
||||
} else if (next_station.Contains(cargo_next)) {
|
||||
} else if (std::ranges::find(next_station, cargo_next) != std::end(next_station)) {
|
||||
return MTA_KEEP;
|
||||
} else {
|
||||
return MTA_TRANSFER;
|
||||
@@ -425,14 +425,14 @@ void VehicleCargoList::AgeCargo()
|
||||
* @param accepted If the cargo will be accepted at the station.
|
||||
* @param current_station ID of the station.
|
||||
* @param next_station ID of the station the vehicle will go to next.
|
||||
* @param order_flags OrderUnloadFlags that will apply to the unload operation.
|
||||
* @param unload_type OrderUnloadType that will apply to the unload operation.
|
||||
* @param ge GoodsEntry for getting the flows.
|
||||
* @param cargo The cargo type of the cargo.
|
||||
* @param payment Payment object for registering transfers.
|
||||
* @param current_tile Current tile the cargo handling is happening on.
|
||||
* return If any cargo will be unloaded.
|
||||
*/
|
||||
bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
|
||||
bool VehicleCargoList::Stage(bool accepted, StationID current_station, std::span<const StationID> next_station, OrderUnloadType unload_type, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
|
||||
{
|
||||
this->AssertCountConsistency();
|
||||
assert(this->action_counts[MTA_LOAD] == 0);
|
||||
@@ -444,9 +444,9 @@ bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationID
|
||||
static const FlowStatMap EMPTY_FLOW_STAT_MAP = {};
|
||||
const FlowStatMap &flows = ge->HasData() ? ge->GetData().flows : EMPTY_FLOW_STAT_MAP;
|
||||
|
||||
bool force_keep = (order_flags & OUFB_NO_UNLOAD) != 0;
|
||||
bool force_unload = (order_flags & OUFB_UNLOAD) != 0;
|
||||
bool force_transfer = (order_flags & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0;
|
||||
bool force_keep = unload_type == OrderUnloadType::NoUnload;
|
||||
bool force_unload = unload_type == OrderUnloadType::Unload;
|
||||
bool force_transfer = unload_type == OrderUnloadType::Transfer || unload_type == OrderUnloadType::Unload;
|
||||
assert(this->count > 0 || it == this->packets.end());
|
||||
while (sum < this->count) {
|
||||
CargoPacket *cp = *it;
|
||||
@@ -468,9 +468,9 @@ bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationID
|
||||
} else {
|
||||
FlowStat new_shares = flow_it->second;
|
||||
new_shares.ChangeShare(current_station, INT_MIN);
|
||||
StationIDStack excluded = next_station;
|
||||
while (!excluded.IsEmpty() && !new_shares.GetShares()->empty()) {
|
||||
new_shares.ChangeShare(excluded.Pop(), INT_MIN);
|
||||
for (auto station_it = next_station.rbegin(); station_it != next_station.rend(); ++station_it) {
|
||||
if (new_shares.GetShares()->empty()) break;
|
||||
new_shares.ChangeShare(*station_it, INT_MIN);
|
||||
}
|
||||
if (new_shares.GetShares()->empty()) {
|
||||
cargo_next = StationID::Invalid();
|
||||
@@ -739,11 +739,11 @@ bool StationCargoList::ShiftCargo(Taction &action, StationID next)
|
||||
* @return Amount of cargo actually moved.
|
||||
*/
|
||||
template <class Taction>
|
||||
uint StationCargoList::ShiftCargo(Taction action, StationIDStack next, bool include_invalid)
|
||||
uint StationCargoList::ShiftCargo(Taction action, std::span<const StationID> next, bool include_invalid)
|
||||
{
|
||||
uint max_move = action.MaxMove();
|
||||
while (!next.IsEmpty()) {
|
||||
this->ShiftCargo(action, next.Pop());
|
||||
for (auto it = next.rbegin(); it != next.rend(); ++it) {
|
||||
this->ShiftCargo(action, *it);
|
||||
if (action.MaxMove() == 0) break;
|
||||
}
|
||||
if (include_invalid && action.MaxMove() > 0) {
|
||||
@@ -814,7 +814,7 @@ uint StationCargoList::Truncate(uint max_move, StationCargoAmountMap *cargo_per_
|
||||
* @param current_tile Current tile the cargo handling is happening on.
|
||||
* @return Amount of cargo actually reserved.
|
||||
*/
|
||||
uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, StationIDStack next_station, TileIndex current_tile)
|
||||
uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, std::span<const StationID> next_station, TileIndex current_tile)
|
||||
{
|
||||
return this->ShiftCargo(CargoReservation(this, dest, max_move, current_tile), next_station, true);
|
||||
}
|
||||
@@ -831,7 +831,7 @@ uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, StationIDS
|
||||
* modes of loading are exclusive, though. If cargo is reserved we don't
|
||||
* need to load unreserved cargo.
|
||||
*/
|
||||
uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, StationIDStack next_station, TileIndex current_tile)
|
||||
uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, std::span<const StationID> next_station, TileIndex current_tile)
|
||||
{
|
||||
uint move = std::min(dest->ActionCount(VehicleCargoList::MTA_LOAD), max_move);
|
||||
if (move > 0) {
|
||||
@@ -839,7 +839,7 @@ uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, StationIDStac
|
||||
dest->Reassign<VehicleCargoList::MTA_LOAD, VehicleCargoList::MTA_KEEP>(move);
|
||||
return move;
|
||||
} else {
|
||||
return this->ShiftCargo(CargoLoad(this, dest, max_move, current_tile), next_station, true);
|
||||
return this->ShiftCargo(CargoLoad{this, dest, max_move, current_tile}, next_station, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -853,7 +853,7 @@ uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, StationIDStac
|
||||
*/
|
||||
uint StationCargoList::Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
|
||||
{
|
||||
return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), avoid, false);
|
||||
return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), {&avoid, 1}, false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+8
-8
@@ -371,7 +371,7 @@ protected:
|
||||
void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count);
|
||||
|
||||
static MoveToAction ChooseAction(const CargoPacket *cp, StationID cargo_next,
|
||||
StationID current_station, bool accepted, StationIDStack next_station);
|
||||
StationID current_station, bool accepted, std::span<const StationID> next_station);
|
||||
|
||||
public:
|
||||
/** The station cargo list needs to control the unloading. */
|
||||
@@ -469,7 +469,7 @@ public:
|
||||
|
||||
void InvalidateCache();
|
||||
|
||||
bool Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile);
|
||||
bool Stage(bool accepted, StationID current_station, std::span<const StationID> next_station, OrderUnloadType unload_type, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile);
|
||||
|
||||
/**
|
||||
* Marks all cargo in the vehicle as to be kept. This is mostly useful for
|
||||
@@ -543,7 +543,7 @@ public:
|
||||
bool ShiftCargo(Taction &action, StationID next);
|
||||
|
||||
template <class Taction>
|
||||
uint ShiftCargo(Taction action, StationIDStack next, bool include_invalid);
|
||||
uint ShiftCargo(Taction action, std::span<const StationID> next, bool include_invalid);
|
||||
|
||||
void Append(CargoPacket *cp, StationID next);
|
||||
|
||||
@@ -552,10 +552,10 @@ public:
|
||||
* @param next Station the cargo is headed for.
|
||||
* @return If there is any cargo for that station.
|
||||
*/
|
||||
inline bool HasCargoFor(StationIDStack next) const
|
||||
inline bool HasCargoFor(std::span<const StationID> next) const
|
||||
{
|
||||
while (!next.IsEmpty()) {
|
||||
if (this->packets.find(next.Pop()) != this->packets.end()) return true;
|
||||
for (const StationID &station : next) {
|
||||
if (this->packets.find(station) != this->packets.end()) return true;
|
||||
}
|
||||
/* Packets for StationID::Invalid() can go anywhere. */
|
||||
return this->packets.find(StationID::Invalid()) != this->packets.end();
|
||||
@@ -603,8 +603,8 @@ public:
|
||||
* amount of cargo to be moved. Second parameter is destination (if
|
||||
* applicable), return value is amount of cargo actually moved. */
|
||||
|
||||
uint Reserve(uint max_move, VehicleCargoList *dest, StationIDStack next, TileIndex current_tile);
|
||||
uint Load(uint max_move, VehicleCargoList *dest, StationIDStack next, TileIndex current_tile);
|
||||
uint Reserve(uint max_move, VehicleCargoList *dest, std::span<const StationID> next, TileIndex current_tile);
|
||||
uint Load(uint max_move, VehicleCargoList *dest, std::span<const StationID> next, TileIndex current_tile);
|
||||
uint Truncate(uint max_move = UINT_MAX, StationCargoAmountMap *cargo_per_source = nullptr);
|
||||
uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
|
||||
|
||||
|
||||
+1
-1
@@ -219,7 +219,7 @@ static const CheatEntry _cheats_ui[] = {
|
||||
static_assert(CHT_NUM_CHEATS == lengthof(_cheats_ui));
|
||||
|
||||
/** Widget definitions of the cheat GUI. */
|
||||
static constexpr NWidgetPart _nested_cheat_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_cheat_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_CHEATS, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
|
||||
+1
-1
@@ -226,7 +226,7 @@ static inline bool NeighbourIsNormal(TileIndex tile)
|
||||
TileIndex t = tile + TileOffsByDiagDir(dir);
|
||||
if (!IsValidTile(t)) continue;
|
||||
if (GetTropicZone(t) != TROPICZONE_DESERT) return true;
|
||||
if (HasTileWaterClass(t) && GetWaterClass(t) == WATER_CLASS_SEA) return true;
|
||||
if (HasTileWaterClass(t) && GetWaterClass(t) == WaterClass::Sea) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+1
-1
@@ -274,7 +274,7 @@ inline void MakeField(Tile t, uint field_type, IndustryID industry)
|
||||
t.m3() = field_type;
|
||||
t.m4() = 0 << 5 | 0 << 2;
|
||||
SetClearGroundDensity(t, CLEAR_FIELDS, 3);
|
||||
SB(t.m6(), 2, 4, 0);
|
||||
SB(t.m6(), 2, 6, 0);
|
||||
t.m7() = 0;
|
||||
t.m8() = 0;
|
||||
}
|
||||
|
||||
+13
-13
@@ -144,21 +144,21 @@ std::string_view GetCommandName(Commands cmd)
|
||||
bool IsCommandAllowedWhilePaused(Commands cmd)
|
||||
{
|
||||
/* Lookup table for the command types that are allowed for a given pause level setting. */
|
||||
static const int command_type_lookup[] = {
|
||||
CMDPL_ALL_ACTIONS, ///< CMDT_LANDSCAPE_CONSTRUCTION
|
||||
CMDPL_NO_LANDSCAPING, ///< CMDT_VEHICLE_CONSTRUCTION
|
||||
CMDPL_NO_LANDSCAPING, ///< CMDT_MONEY_MANAGEMENT
|
||||
CMDPL_NO_CONSTRUCTION, ///< CMDT_VEHICLE_MANAGEMENT
|
||||
CMDPL_NO_CONSTRUCTION, ///< CMDT_ROUTE_MANAGEMENT
|
||||
CMDPL_NO_CONSTRUCTION, ///< CMDT_OTHER_MANAGEMENT
|
||||
CMDPL_NO_ACTIONS, ///< CMDT_COMPANY_SETTING
|
||||
CMDPL_NO_ACTIONS, ///< CMDT_SERVER_SETTING
|
||||
CMDPL_NO_ACTIONS, ///< CMDT_CHEAT
|
||||
static constexpr CommandPauseLevel command_type_lookup[] = {
|
||||
CommandPauseLevel::AllActions, // CommandType::LandscapeConstruction
|
||||
CommandPauseLevel::NoLandscaping, // CommandType::VehicleConstruction
|
||||
CommandPauseLevel::NoLandscaping, // CommandType::MoneyManagement
|
||||
CommandPauseLevel::NoConstruction, // CommandType::VehicleManagement
|
||||
CommandPauseLevel::NoConstruction, // CommandType::RouteManagement
|
||||
CommandPauseLevel::NoConstruction, // CommandType::OtherManagement
|
||||
CommandPauseLevel::NoActions, // CommandType::CompanySetting
|
||||
CommandPauseLevel::NoActions, // CommandType::ServerSetting
|
||||
CommandPauseLevel::NoActions, // CommandType::Cheat
|
||||
};
|
||||
static_assert(lengthof(command_type_lookup) == CMDT_END);
|
||||
static_assert(std::size(command_type_lookup) == to_underlying(CommandType::End));
|
||||
|
||||
assert(IsValidCommand(cmd));
|
||||
return _game_mode == GM_EDITOR || command_type_lookup[_command_proc_table[cmd].type] <= _settings_game.construction.command_pause_level;
|
||||
return _game_mode == GM_EDITOR || command_type_lookup[to_underlying(_command_proc_table[cmd].type)] <= _settings_game.construction.command_pause_level;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -384,7 +384,7 @@ CommandCost CommandHelperBase::InternalExecuteProcessResult(Commands cmd, Comman
|
||||
SubtractMoneyFromCompany(res_exec);
|
||||
|
||||
/* Record if there was a command issues during pause; ignore pause/other setting related changes. */
|
||||
if (_pause_mode.Any() && _command_proc_table[cmd].type != CMDT_SERVER_SETTING) _pause_mode.Set(PauseMode::CommandDuringPause);
|
||||
if (_pause_mode.Any() && _command_proc_table[cmd].type != CommandType::ServerSetting) _pause_mode.Set(PauseMode::CommandDuringPause);
|
||||
|
||||
/* update signals if needed */
|
||||
UpdateSignalsInBuffer();
|
||||
|
||||
+21
-17
@@ -214,6 +214,7 @@ enum Commands : uint8_t {
|
||||
|
||||
CMD_BUILD_RAIL_WAYPOINT, ///< build a waypoint
|
||||
CMD_RENAME_WAYPOINT, ///< rename a waypoint
|
||||
CMD_MOVE_WAYPOINT_NAME, ///< move a waypoint name
|
||||
CMD_REMOVE_FROM_RAIL_WAYPOINT, ///< remove a (rectangle of) tiles from a rail waypoint
|
||||
|
||||
CMD_BUILD_ROAD_WAYPOINT, ///< build a road waypoint
|
||||
@@ -275,10 +276,12 @@ enum Commands : uint8_t {
|
||||
CMD_RENAME_COMPANY, ///< change the company name
|
||||
CMD_RENAME_PRESIDENT, ///< change the president name
|
||||
CMD_RENAME_STATION, ///< rename a station
|
||||
CMD_MOVE_STATION_NAME, ///< move a station name
|
||||
CMD_RENAME_DEPOT, ///< rename a depot
|
||||
|
||||
CMD_PLACE_SIGN, ///< place a sign
|
||||
CMD_RENAME_SIGN, ///< rename a sign
|
||||
CMD_MOVE_SIGN, ///< move a sign
|
||||
|
||||
CMD_TURN_ROADVEH, ///< turn a road vehicle around
|
||||
|
||||
@@ -380,7 +383,7 @@ enum Commands : uint8_t {
|
||||
*
|
||||
* This enums defines some flags which can be used for the commands.
|
||||
*/
|
||||
enum DoCommandFlag : uint8_t {
|
||||
enum class DoCommandFlag : uint8_t {
|
||||
Execute, ///< execute the given command
|
||||
Auto, ///< don't allow building on structures
|
||||
QueryCost, ///< query cost only, don't build.
|
||||
@@ -417,26 +420,27 @@ enum class CommandFlag : uint8_t {
|
||||
using CommandFlags = EnumBitSet<CommandFlag, uint16_t>;
|
||||
|
||||
/** Types of commands we have. */
|
||||
enum CommandType : uint8_t {
|
||||
CMDT_LANDSCAPE_CONSTRUCTION, ///< Construction and destruction of objects on the map.
|
||||
CMDT_VEHICLE_CONSTRUCTION, ///< Construction, modification (incl. refit) and destruction of vehicles.
|
||||
CMDT_MONEY_MANAGEMENT, ///< Management of money, i.e. loans.
|
||||
CMDT_VEHICLE_MANAGEMENT, ///< Stopping, starting, sending to depot, turning around, replace orders etc.
|
||||
CMDT_ROUTE_MANAGEMENT, ///< Modifications to route management (orders, groups, etc).
|
||||
CMDT_OTHER_MANAGEMENT, ///< Renaming stuff, changing company colours, placing signs, etc.
|
||||
CMDT_COMPANY_SETTING, ///< Changing settings related to a company.
|
||||
CMDT_SERVER_SETTING, ///< Pausing/removing companies/server settings.
|
||||
CMDT_CHEAT, ///< A cheat of some sorts.
|
||||
enum class CommandType : uint8_t {
|
||||
LandscapeConstruction, ///< Construction and destruction of objects on the map.
|
||||
VehicleConstruction, ///< Construction, modification (incl. refit) and destruction of vehicles.
|
||||
MoneyManagement, ///< Management of money, i.e. loans.
|
||||
VehicleManagement, ///< Stopping, starting, sending to depot, turning around, replace orders etc.
|
||||
RouteManagement, ///< Modifications to route management (orders, groups, etc).
|
||||
OtherManagement, ///< Renaming stuff, changing company colours, placing signs, etc.
|
||||
CompanySetting, ///< Changing settings related to a company.
|
||||
ServerSetting, ///< Pausing/removing companies/server settings.
|
||||
Cheat, ///< A cheat of some sorts.
|
||||
|
||||
CMDT_END, ///< Magic end marker.
|
||||
End, ///< End marker.
|
||||
};
|
||||
|
||||
/** Different command pause levels. */
|
||||
enum CommandPauseLevel : uint8_t {
|
||||
CMDPL_NO_ACTIONS, ///< No user actions may be executed.
|
||||
CMDPL_NO_CONSTRUCTION, ///< No construction actions may be executed.
|
||||
CMDPL_NO_LANDSCAPING, ///< No landscaping actions may be executed.
|
||||
CMDPL_ALL_ACTIONS, ///< All actions may be executed.
|
||||
|
||||
enum class CommandPauseLevel : uint8_t {
|
||||
NoActions, ///< No user actions may be executed.
|
||||
NoConstruction, ///< No construction actions may be executed.
|
||||
NoLandscaping, ///< No landscaping actions may be executed.
|
||||
AllActions, ///< All actions may be executed.
|
||||
};
|
||||
|
||||
|
||||
|
||||
+16
-2
@@ -45,8 +45,10 @@ struct CompanyInfrastructure {
|
||||
return std::accumulate(std::begin(this->rail), std::end(this->rail), 0U);
|
||||
}
|
||||
|
||||
uint32_t GetRoadTotal() const;
|
||||
uint32_t GetTramTotal() const;
|
||||
uint32_t GetRoadTramTotal(RoadTramType rtt) const;
|
||||
|
||||
inline uint32_t GetRoadTotal() const { return GetRoadTramTotal(RTT_ROAD); }
|
||||
inline uint32_t GetTramTotal() const { return GetRoadTramTotal(RTT_TRAM); }
|
||||
};
|
||||
|
||||
class FreeUnitIDGenerator {
|
||||
@@ -178,6 +180,18 @@ struct Company : CompanyProperties, CompanyPool::PoolItem<&_company_pool> {
|
||||
return !Company::Get(index)->is_ai;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get offset for recolour palette of specific company.
|
||||
* @param livery_scheme Scheme to use for recolour.
|
||||
* @param use_secondary Specify whether to add secondary colour offset to the result.
|
||||
* @return palette offset.
|
||||
*/
|
||||
inline uint8_t GetCompanyRecolourOffset(LiveryScheme livery_scheme, bool use_secondary = true) const
|
||||
{
|
||||
const Livery &l = this->livery[livery_scheme];
|
||||
return use_secondary ? l.colour1 + l.colour2 * 16 : l.colour1;
|
||||
}
|
||||
|
||||
static void PostDestructor(size_t index);
|
||||
};
|
||||
|
||||
|
||||
+21
-33
@@ -574,14 +574,14 @@ restart:;
|
||||
void ResetCompanyLivery(Company *c)
|
||||
{
|
||||
for (LiveryScheme scheme = LS_BEGIN; scheme < LS_END; scheme++) {
|
||||
c->livery[scheme].in_use = 0;
|
||||
c->livery[scheme].in_use.Reset();
|
||||
c->livery[scheme].colour1 = c->colour;
|
||||
c->livery[scheme].colour2 = c->colour;
|
||||
}
|
||||
|
||||
for (Group *g : Group::Iterate()) {
|
||||
if (g->owner == c->index) {
|
||||
g->livery.in_use = 0;
|
||||
g->livery.in_use.Reset();
|
||||
g->livery.colour1 = c->colour;
|
||||
g->livery.colour2 = c->colour;
|
||||
}
|
||||
@@ -623,8 +623,8 @@ Company *DoStartupNewCompany(bool is_ai, CompanyID company = CompanyID::Invalid(
|
||||
c->inaugurated_year = TimerGameEconomy::year;
|
||||
c->inaugurated_year_calendar = TimerGameCalendar::year;
|
||||
|
||||
/* If starting a player company in singleplayer and a favorite company manager face is selected, choose it. Otherwise, use a random face.
|
||||
* In a network game, we'll choose the favorite face later in CmdCompanyCtrl to sync it to all clients. */
|
||||
/* If starting a player company in singleplayer and a favourite company manager face is selected, choose it. Otherwise, use a random face.
|
||||
* In a network game, we'll choose the favourite face later in CmdCompanyCtrl to sync it to all clients. */
|
||||
bool randomise_face = true;
|
||||
if (!_company_manager_face.empty() && !is_ai && !_networking) {
|
||||
auto cmf = ParseCompanyManagerFaceCode(_company_manager_face);
|
||||
@@ -917,7 +917,7 @@ CommandCost CmdCompanyCtrl(DoCommandFlags flags, CompanyCtrlAction cca, CompanyI
|
||||
SetLocalCompany(c->index);
|
||||
|
||||
/*
|
||||
* If a favorite company manager face is selected, choose it. Otherwise, use a random face.
|
||||
* If a favourite company manager face is selected, choose it. Otherwise, use a random face.
|
||||
* Because this needs to be synchronised over the network, only the client knows
|
||||
* its configuration and we are currently in the execution of a command, we have
|
||||
* to circumvent the normal ::Post logic for commands and just send the command.
|
||||
@@ -925,7 +925,7 @@ CommandCost CmdCompanyCtrl(DoCommandFlags flags, CompanyCtrlAction cca, CompanyI
|
||||
if (!_company_manager_face.empty()) {
|
||||
auto cmf = ParseCompanyManagerFaceCode(_company_manager_face);
|
||||
if (cmf.has_value()) {
|
||||
Command<CMD_SET_COMPANY_MANAGER_FACE>::SendNet(STR_NULL, c->index, cmf->bits, cmf->style);
|
||||
Command<CMD_SET_COMPANY_MANAGER_FACE>::SendNet(STR_NULL, c->index, cmf->style, cmf->bits);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1050,11 +1050,11 @@ CommandCost CmdCompanyAllowListCtrl(DoCommandFlags flags, CompanyAllowListCtrlAc
|
||||
/**
|
||||
* Change the company manager's face.
|
||||
* @param flags operation to perform
|
||||
* @param bits The bits of company manager face.
|
||||
* @param style The style of the company manager face.
|
||||
* @param bits The bits of company manager face.
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdSetCompanyManagerFace(DoCommandFlags flags, uint32_t bits, uint style)
|
||||
CommandCost CmdSetCompanyManagerFace(DoCommandFlags flags, uint style, uint32_t bits)
|
||||
{
|
||||
CompanyManagerFace tmp_face{style, bits, {}};
|
||||
if (!IsValidCompanyManagerFace(tmp_face)) return CMD_ERROR;
|
||||
@@ -1077,8 +1077,8 @@ CommandCost CmdSetCompanyManagerFace(DoCommandFlags flags, uint32_t bits, uint s
|
||||
void UpdateCompanyLiveries(Company *c)
|
||||
{
|
||||
for (int i = 1; i < LS_END; i++) {
|
||||
if (!HasBit(c->livery[i].in_use, 0)) c->livery[i].colour1 = c->livery[LS_DEFAULT].colour1;
|
||||
if (!HasBit(c->livery[i].in_use, 1)) c->livery[i].colour2 = c->livery[LS_DEFAULT].colour2;
|
||||
if (!c->livery[i].in_use.Test(Livery::Flag::Primary)) c->livery[i].colour1 = c->livery[LS_DEFAULT].colour1;
|
||||
if (!c->livery[i].in_use.Test(Livery::Flag::Secondary)) c->livery[i].colour2 = c->livery[LS_DEFAULT].colour2;
|
||||
}
|
||||
UpdateCompanyGroupLiveries(c);
|
||||
}
|
||||
@@ -1109,7 +1109,7 @@ CommandCost CmdSetCompanyColour(DoCommandFlags flags, LiveryScheme scheme, bool
|
||||
|
||||
if (flags.Test(DoCommandFlag::Execute)) {
|
||||
if (primary) {
|
||||
if (scheme != LS_DEFAULT) AssignBit(c->livery[scheme].in_use, 0, colour != INVALID_COLOUR);
|
||||
if (scheme != LS_DEFAULT) c->livery[scheme].in_use.Set(Livery::Flag::Primary, colour != INVALID_COLOUR);
|
||||
if (colour == INVALID_COLOUR) colour = c->livery[LS_DEFAULT].colour1;
|
||||
c->livery[scheme].colour1 = colour;
|
||||
|
||||
@@ -1122,7 +1122,7 @@ CommandCost CmdSetCompanyColour(DoCommandFlags flags, LiveryScheme scheme, bool
|
||||
CompanyAdminUpdate(c);
|
||||
}
|
||||
} else {
|
||||
if (scheme != LS_DEFAULT) AssignBit(c->livery[scheme].in_use, 1, colour != INVALID_COLOUR);
|
||||
if (scheme != LS_DEFAULT) c->livery[scheme].in_use.Set(Livery::Flag::Secondary, colour != INVALID_COLOUR);
|
||||
if (colour == INVALID_COLOUR) colour = c->livery[LS_DEFAULT].colour2;
|
||||
c->livery[scheme].colour2 = colour;
|
||||
|
||||
@@ -1131,16 +1131,16 @@ CommandCost CmdSetCompanyColour(DoCommandFlags flags, LiveryScheme scheme, bool
|
||||
}
|
||||
}
|
||||
|
||||
if (c->livery[scheme].in_use != 0) {
|
||||
if (c->livery[scheme].in_use.Any({Livery::Flag::Primary, Livery::Flag::Secondary})) {
|
||||
/* If enabling a scheme, set the default scheme to be in use too */
|
||||
c->livery[LS_DEFAULT].in_use = 1;
|
||||
c->livery[LS_DEFAULT].in_use.Set(Livery::Flag::Primary);
|
||||
} else {
|
||||
/* Else loop through all schemes to see if any are left enabled.
|
||||
* If not, disable the default scheme too. */
|
||||
c->livery[LS_DEFAULT].in_use = 0;
|
||||
c->livery[LS_DEFAULT].in_use.Reset({Livery::Flag::Primary, Livery::Flag::Secondary});
|
||||
for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
|
||||
if (c->livery[scheme].in_use != 0) {
|
||||
c->livery[LS_DEFAULT].in_use = 1;
|
||||
if (c->livery[scheme].in_use.Any({Livery::Flag::Primary, Livery::Flag::Secondary})) {
|
||||
c->livery[LS_DEFAULT].in_use.Set(Livery::Flag::Primary);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1291,26 +1291,14 @@ int CompanyServiceInterval(const Company *c, VehicleType type)
|
||||
|
||||
/**
|
||||
* Get total sum of all owned road bits.
|
||||
* @param rtt RoadTramType to get total for.
|
||||
* @return Combined total road road bits.
|
||||
*/
|
||||
uint32_t CompanyInfrastructure::GetRoadTotal() const
|
||||
uint32_t CompanyInfrastructure::GetRoadTramTotal(RoadTramType rtt) const
|
||||
{
|
||||
uint32_t total = 0;
|
||||
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
|
||||
if (RoadTypeIsRoad(rt)) total += this->road[rt];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total sum of all owned tram bits.
|
||||
* @return Combined total of tram road bits.
|
||||
*/
|
||||
uint32_t CompanyInfrastructure::GetTramTotal() const
|
||||
{
|
||||
uint32_t total = 0;
|
||||
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
|
||||
if (RoadTypeIsTram(rt)) total += this->road[rt];
|
||||
for (RoadType rt : GetMaskForRoadTramType(rtt)) {
|
||||
total += this->road[rt];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
+7
-7
@@ -25,12 +25,12 @@ CommandCost CmdRenamePresident(DoCommandFlags flags, const std::string &text);
|
||||
CommandCost CmdSetCompanyManagerFace(DoCommandFlags flags, uint style, uint32_t bits);
|
||||
CommandCost CmdSetCompanyColour(DoCommandFlags flags, LiveryScheme scheme, bool primary, Colours colour);
|
||||
|
||||
DEF_CMD_TRAIT(CMD_COMPANY_CTRL, CmdCompanyCtrl, CommandFlags({CommandFlag::Spectator, CommandFlag::ClientID, CommandFlag::NoEst}), CMDT_SERVER_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_COMPANY_ALLOW_LIST_CTRL, CmdCompanyAllowListCtrl, CommandFlag::NoEst, CMDT_SERVER_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_GIVE_MONEY, CmdGiveMoney, {}, CMDT_MONEY_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_RENAME_COMPANY, CmdRenameCompany, {}, CMDT_COMPANY_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_RENAME_PRESIDENT, CmdRenamePresident, {}, CMDT_COMPANY_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_SET_COMPANY_MANAGER_FACE, CmdSetCompanyManagerFace, {}, CMDT_COMPANY_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_SET_COMPANY_COLOUR, CmdSetCompanyColour, {}, CMDT_COMPANY_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_COMPANY_CTRL, CmdCompanyCtrl, CommandFlags({CommandFlag::Spectator, CommandFlag::ClientID, CommandFlag::NoEst}), CommandType::ServerSetting)
|
||||
DEF_CMD_TRAIT(CMD_COMPANY_ALLOW_LIST_CTRL, CmdCompanyAllowListCtrl, CommandFlag::NoEst, CommandType::ServerSetting)
|
||||
DEF_CMD_TRAIT(CMD_GIVE_MONEY, CmdGiveMoney, {}, CommandType::MoneyManagement)
|
||||
DEF_CMD_TRAIT(CMD_RENAME_COMPANY, CmdRenameCompany, {}, CommandType::CompanySetting)
|
||||
DEF_CMD_TRAIT(CMD_RENAME_PRESIDENT, CmdRenamePresident, {}, CommandType::CompanySetting)
|
||||
DEF_CMD_TRAIT(CMD_SET_COMPANY_MANAGER_FACE, CmdSetCompanyManagerFace, {}, CommandType::CompanySetting)
|
||||
DEF_CMD_TRAIT(CMD_SET_COMPANY_COLOUR, CmdSetCompanyColour, {}, CommandType::CompanySetting)
|
||||
|
||||
#endif /* COMPANY_CMD_H */
|
||||
|
||||
+22
-22
@@ -286,7 +286,7 @@ static void DrawYearColumn(const Rect &r, TimerGameEconomy::Year year, const Exp
|
||||
DrawPrice(sum, r.left, r.right, y, TC_WHITE);
|
||||
}
|
||||
|
||||
static constexpr NWidgetPart _nested_company_finances_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_company_finances_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_CF_CAPTION),
|
||||
@@ -655,7 +655,7 @@ private:
|
||||
}
|
||||
|
||||
uint8_t sel;
|
||||
if (default_livery == nullptr || HasBit(livery->in_use, primary ? 0 : 1)) {
|
||||
if (default_livery == nullptr || livery->in_use.Test(primary ? Livery::Flag::Primary : Livery::Flag::Secondary)) {
|
||||
sel = primary ? livery->colour1 : livery->colour2;
|
||||
} else {
|
||||
sel = default_col;
|
||||
@@ -697,6 +697,7 @@ public:
|
||||
SelectCompanyLiveryWindow(WindowDesc &desc, CompanyID company, GroupID group) : Window(desc)
|
||||
{
|
||||
this->CreateNestedTree();
|
||||
this->GetWidget<NWidgetStacked>(WID_SCL_SEC_COL_DROP_SEL)->SetDisplayedPlane(_loaded_newgrf_features.has_2CC ? 0 : SZSP_NONE);
|
||||
this->vscroll = this->GetScrollbar(WID_SCL_MATRIX_SCROLLBAR);
|
||||
|
||||
if (group == GroupID::Invalid()) {
|
||||
@@ -767,10 +768,7 @@ public:
|
||||
}
|
||||
|
||||
case WID_SCL_SEC_COL_DROPDOWN:
|
||||
if (!_loaded_newgrf_features.has_2CC) {
|
||||
size.width = 0;
|
||||
break;
|
||||
}
|
||||
if (!_loaded_newgrf_features.has_2CC) break;
|
||||
[[fallthrough]];
|
||||
|
||||
case WID_SCL_PRI_COL_DROPDOWN: {
|
||||
@@ -819,7 +817,7 @@ public:
|
||||
}
|
||||
if (scheme == LS_END) scheme = LS_DEFAULT;
|
||||
const Livery *livery = &c->livery[scheme];
|
||||
if (scheme == LS_DEFAULT || HasBit(livery->in_use, primary ? 0 : 1)) {
|
||||
if (scheme == LS_DEFAULT || livery->in_use.Test(primary ? Livery::Flag::Primary : Livery::Flag::Secondary)) {
|
||||
colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2);
|
||||
}
|
||||
}
|
||||
@@ -827,7 +825,7 @@ public:
|
||||
if (this->sel != GroupID::Invalid()) {
|
||||
const Group *g = Group::Get(this->sel);
|
||||
const Livery *livery = &g->livery;
|
||||
if (HasBit(livery->in_use, primary ? 0 : 1)) {
|
||||
if (livery->in_use.Test(primary ? Livery::Flag::Primary : Livery::Flag::Secondary)) {
|
||||
colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2);
|
||||
}
|
||||
}
|
||||
@@ -875,12 +873,12 @@ public:
|
||||
|
||||
/* Text below the first dropdown. */
|
||||
DrawSprite(SPR_SQUARE, GetColourPalette(livery.colour1), pri_squ.left, y + square_offs);
|
||||
DrawString(pri.left, pri.right, y + text_offs, (is_default_scheme || HasBit(livery.in_use, 0)) ? STR_COLOUR_DARK_BLUE + livery.colour1 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD);
|
||||
DrawString(pri.left, pri.right, y + text_offs, (is_default_scheme || livery.in_use.Test(Livery::Flag::Primary)) ? STR_COLOUR_DARK_BLUE + livery.colour1 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD);
|
||||
|
||||
/* Text below the second dropdown. */
|
||||
if (sec.right > sec.left) { // Second dropdown has non-zero size.
|
||||
DrawSprite(SPR_SQUARE, GetColourPalette(livery.colour2), sec_squ.left, y + square_offs);
|
||||
DrawString(sec.left, sec.right, y + text_offs, (is_default_scheme || HasBit(livery.in_use, 1)) ? STR_COLOUR_DARK_BLUE + livery.colour2 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD);
|
||||
DrawString(sec.left, sec.right, y + text_offs, (is_default_scheme || livery.in_use.Test(Livery::Flag::Secondary)) ? STR_COLOUR_DARK_BLUE + livery.colour2 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD);
|
||||
}
|
||||
|
||||
y += this->line_height;
|
||||
@@ -1062,7 +1060,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr NWidgetPart _nested_select_company_livery_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_select_company_livery_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCL_CAPTION),
|
||||
@@ -1089,13 +1087,15 @@ static constexpr NWidgetPart _nested_select_company_livery_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_SCL_SPACER_DROPDOWN), SetFill(1, 1), SetResize(1, 0), EndContainer(),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_PRI_COL_DROPDOWN), SetFill(0, 1), SetToolTip(STR_LIVERY_PRIMARY_TOOLTIP),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_SEC_COL_DROPDOWN), SetFill(0, 1), SetToolTip(STR_LIVERY_SECONDARY_TOOLTIP),
|
||||
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCL_SEC_COL_DROP_SEL),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_SEC_COL_DROPDOWN), SetFill(0, 1), SetToolTip(STR_LIVERY_SECONDARY_TOOLTIP),
|
||||
EndContainer(),
|
||||
NWidget(WWT_RESIZEBOX, COLOUR_GREY),
|
||||
EndContainer(),
|
||||
};
|
||||
|
||||
static WindowDesc _select_company_livery_desc(
|
||||
WDP_AUTO, "company_color_scheme", 0, 0,
|
||||
WDP_AUTO, "company_colour_scheme", 0, 0,
|
||||
WC_COMPANY_COLOUR, WC_NONE,
|
||||
{},
|
||||
_nested_select_company_livery_widgets
|
||||
@@ -1161,7 +1161,7 @@ void DrawCompanyManagerFace(const CompanyManagerFace &cmf, Colours colour, const
|
||||
}
|
||||
|
||||
/** Nested widget description for the company manager face selection dialog */
|
||||
static constexpr NWidgetPart _nested_select_company_manager_face_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_select_company_manager_face_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCMF_CAPTION), SetStringTip(STR_FACE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
@@ -1333,8 +1333,8 @@ public:
|
||||
Rect ir = r.Shrink(WidgetDimensions::scaled.frametext, RectPadding::zero).WithHeight(this->line_height);
|
||||
bool rtl = _current_text_dir == TD_RTL;
|
||||
|
||||
Rect br = ir.CentreTo(ir.Width(), SETTING_BUTTON_HEIGHT).WithWidth(SETTING_BUTTON_WIDTH, rtl);
|
||||
Rect tr = ir.Shrink(RectPadding::zero, WidgetDimensions::scaled.matrix).CentreTo(ir.Width(), GetCharacterHeight(FS_NORMAL)).Indent(SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide, rtl);
|
||||
Rect br = ir.CentreToHeight(SETTING_BUTTON_HEIGHT).WithWidth(SETTING_BUTTON_WIDTH, rtl);
|
||||
Rect tr = ir.Shrink(RectPadding::zero, WidgetDimensions::scaled.matrix).CentreToHeight(GetCharacterHeight(FS_NORMAL)).Indent(SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide, rtl);
|
||||
|
||||
DrawArrowButtons(br.left, br.top, COLOUR_YELLOW, this->selected_var == UINT_MAX - 1 ? this->click_state : 0, true, true);
|
||||
DrawString(tr, GetString(STR_FACE_SETTING_NUMERIC, STR_FACE_STYLE, this->face.style + 1, GetNumCompanyManagerFaceStyles()), TC_WHITE);
|
||||
@@ -1352,8 +1352,8 @@ public:
|
||||
const uint8_t var = static_cast<uint8_t>(*it - vars.data());
|
||||
const FaceVar &facevar = **it;
|
||||
|
||||
Rect br = ir.CentreTo(ir.Width(), SETTING_BUTTON_HEIGHT).WithWidth(SETTING_BUTTON_WIDTH, rtl);
|
||||
Rect tr = ir.Shrink(RectPadding::zero, WidgetDimensions::scaled.matrix).CentreTo(ir.Width(), GetCharacterHeight(FS_NORMAL)).Indent(SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide, rtl);
|
||||
Rect br = ir.CentreToHeight(SETTING_BUTTON_HEIGHT).WithWidth(SETTING_BUTTON_WIDTH, rtl);
|
||||
Rect tr = ir.Shrink(RectPadding::zero, WidgetDimensions::scaled.matrix).CentreToHeight(GetCharacterHeight(FS_NORMAL)).Indent(SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide, rtl);
|
||||
|
||||
uint val = vars[var].GetBits(this->face);
|
||||
if (facevar.type == FaceVarType::Toggle) {
|
||||
@@ -1384,7 +1384,7 @@ public:
|
||||
|
||||
/* OK button */
|
||||
case WID_SCMF_ACCEPT:
|
||||
Command<CMD_SET_COMPANY_MANAGER_FACE>::Post(this->face.bits, this->face.style);
|
||||
Command<CMD_SET_COMPANY_MANAGER_FACE>::Post(this->face.style, this->face.bits);
|
||||
[[fallthrough]];
|
||||
|
||||
/* Cancel button */
|
||||
@@ -1536,7 +1536,7 @@ static void DoSelectCompanyManagerFace(Window *parent)
|
||||
new SelectCompanyManagerFaceWindow(_select_company_manager_face_desc, parent);
|
||||
}
|
||||
|
||||
static constexpr NWidgetPart _nested_company_infrastructure_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_company_infrastructure_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_CI_CAPTION),
|
||||
@@ -1840,7 +1840,7 @@ static void ShowCompanyInfrastructure(CompanyID company)
|
||||
AllocateWindowDescFront<CompanyInfrastructureWindow>(_company_infrastructure_desc, company);
|
||||
}
|
||||
|
||||
static constexpr NWidgetPart _nested_company_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_company_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_C_CAPTION),
|
||||
@@ -2405,7 +2405,7 @@ private:
|
||||
Money company_value{}; ///< The value of the company for which the user can buy it.
|
||||
};
|
||||
|
||||
static constexpr NWidgetPart _nested_buy_company_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_buy_company_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
|
||||
NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE, WID_BC_CAPTION),
|
||||
|
||||
+30
-14
@@ -46,6 +46,10 @@
|
||||
#include "company_cmd.h"
|
||||
#include "misc_cmd.h"
|
||||
|
||||
#if defined(WITH_ZLIB)
|
||||
#include "network/network_content.h"
|
||||
#endif /* WITH_ZLIB */
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
@@ -2163,7 +2167,7 @@ static bool ConNetworkAuthorizedKey(std::span<std::string_view> argv)
|
||||
}
|
||||
|
||||
for (auto [name, authorized_keys] : _console_cmd_authorized_keys) {
|
||||
if (StrEqualsIgnoreCase(type, name)) continue;
|
||||
if (!StrEqualsIgnoreCase(type, name)) continue;
|
||||
|
||||
PerformNetworkAuthorizedKeyAction(name, authorized_keys, action, authorized_key);
|
||||
return true;
|
||||
@@ -2176,7 +2180,6 @@ static bool ConNetworkAuthorizedKey(std::span<std::string_view> argv)
|
||||
|
||||
/* Content downloading only is available with ZLIB */
|
||||
#if defined(WITH_ZLIB)
|
||||
#include "network/network_content.h"
|
||||
|
||||
/** Resolve a string to a content type. */
|
||||
static ContentType StringToContentType(std::string_view str)
|
||||
@@ -2316,6 +2319,18 @@ static bool ConContent(std::span<std::string_view> argv)
|
||||
}
|
||||
#endif /* defined(WITH_ZLIB) */
|
||||
|
||||
/**
|
||||
* Get string representation of a font load reason.
|
||||
* @param load_reason The font load reason.
|
||||
* @return String representation.
|
||||
*/
|
||||
static std::string_view FontLoadReasonToName(FontLoadReason load_reason)
|
||||
{
|
||||
static const std::string_view LOAD_REASON_TO_NAME[] = { "default", "configured", "language", "missing" };
|
||||
static_assert(std::size(LOAD_REASON_TO_NAME) == to_underlying(FontLoadReason::End));
|
||||
return LOAD_REASON_TO_NAME[to_underlying(load_reason)];
|
||||
}
|
||||
|
||||
static bool ConFont(std::span<std::string_view> argv)
|
||||
{
|
||||
if (argv.empty()) {
|
||||
@@ -2364,17 +2379,18 @@ static bool ConFont(std::span<std::string_view> argv)
|
||||
SetFont(argfs, font, size);
|
||||
}
|
||||
|
||||
for (FontSize fs = FS_BEGIN; fs < FS_END; fs++) {
|
||||
FontCache *fc = FontCache::Get(fs);
|
||||
FontCacheSubSetting *setting = GetFontCacheSubSetting(fs);
|
||||
/* Make sure all non sprite fonts are loaded. */
|
||||
if (!setting->font.empty() && !fc->HasParent()) {
|
||||
FontCache::LoadFontCaches(fs);
|
||||
fc = FontCache::Get(fs);
|
||||
}
|
||||
IConsolePrint(CC_DEFAULT, "{} font:", FontSizeToName(fs));
|
||||
IConsolePrint(CC_DEFAULT, "Currently active: \"{}\", size {}", fc->GetFontName(), fc->GetFontSize());
|
||||
IConsolePrint(CC_DEFAULT, "Requested: \"{}\", size {}", setting->font, setting->size);
|
||||
IConsolePrint(CC_INFO, "Configured fonts:");
|
||||
for (uint i = 0; FontSize fs : FONTSIZES_ALL) {
|
||||
const FontCacheSubSetting *setting = GetFontCacheSubSetting(fs);
|
||||
IConsolePrint(CC_DEFAULT, "{}) {} font: \"{}\", size {}", i, FontSizeToName(fs), setting->font, setting->size);
|
||||
++i;
|
||||
}
|
||||
|
||||
IConsolePrint(CC_INFO, "Currently active fonts:");
|
||||
for (uint i = 0; const auto &fc : FontCache::Get()) {
|
||||
if (fc == nullptr) continue;
|
||||
IConsolePrint(CC_DEFAULT, "{}) {} font: \"{}\" size {} [{}]", i, FontSizeToName(fc->GetSize()), fc->GetFontName(), fc->GetFontSize(), FontLoadReasonToName(fc->GetFontLoadReason()));
|
||||
++i;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -2699,7 +2715,7 @@ static std::string FormatLabel(uint32_t label)
|
||||
return fmt::format("{:c}{:c}{:c}{:c}", GB(label, 24, 8), GB(label, 16, 8), GB(label, 8, 8), GB(label, 0, 8));
|
||||
}
|
||||
|
||||
return fmt::format("{:08X}", std::byteswap(label));
|
||||
return fmt::format("{:08X}", label);
|
||||
}
|
||||
|
||||
static void ConDumpRoadTypes()
|
||||
|
||||
+2
-2
@@ -133,7 +133,7 @@ static inline void IConsoleResetHistoryPos()
|
||||
static std::optional<std::string_view> IConsoleHistoryAdd(std::string_view cmd);
|
||||
static void IConsoleHistoryNavigate(int direction);
|
||||
|
||||
static constexpr NWidgetPart _nested_console_window_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_console_window_widgets = {
|
||||
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_BACKGROUND), SetResize(1, 1),
|
||||
};
|
||||
|
||||
@@ -453,7 +453,7 @@ void IConsoleClose()
|
||||
static std::optional<std::string_view> IConsoleHistoryAdd(std::string_view cmd)
|
||||
{
|
||||
/* Strip all spaces at the begin */
|
||||
while (IsWhitespace(cmd[0])) cmd.remove_prefix(1);
|
||||
while (!cmd.empty() && IsWhitespace(cmd[0])) cmd.remove_prefix(1);
|
||||
|
||||
/* Do not put empty command in history */
|
||||
if (cmd.empty()) return std::nullopt;
|
||||
|
||||
@@ -22,7 +22,6 @@ add_files(
|
||||
pool_type.hpp
|
||||
random_func.cpp
|
||||
random_func.hpp
|
||||
smallstack_type.hpp
|
||||
string_builder.cpp
|
||||
string_builder.hpp
|
||||
string_consumer.cpp
|
||||
|
||||
@@ -254,8 +254,8 @@ public:
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto begin() const { return SetBitIterator<Tvalue_type>(this->data).begin(); }
|
||||
auto end() const { return SetBitIterator<Tvalue_type>(this->data).end(); }
|
||||
auto begin() const { return SetBitIterator<Tvalue_type, Tstorage>(this->data).begin(); }
|
||||
auto end() const { return SetBitIterator<Tvalue_type, Tstorage>(this->data).end(); }
|
||||
|
||||
private:
|
||||
Tstorage data; ///< Bitmask of values.
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
* @param key Key to test.
|
||||
* @return true iff the key exists in the set.
|
||||
*/
|
||||
bool contains(const Tkey &key)
|
||||
bool contains(const Tkey &key) const
|
||||
{
|
||||
return std::ranges::binary_search(this->data, key, Tcompare{});
|
||||
}
|
||||
|
||||
+44
-16
@@ -62,14 +62,14 @@ struct Dimension {
|
||||
|
||||
bool operator< (const Dimension &other) const
|
||||
{
|
||||
int x = (*this).width - other.width;
|
||||
int x = this->width - other.width;
|
||||
if (x != 0) return x < 0;
|
||||
return (*this).height < other.height;
|
||||
return this->height < other.height;
|
||||
}
|
||||
|
||||
bool operator== (const Dimension &other) const
|
||||
{
|
||||
return (*this).width == other.width && (*this).height == other.height;
|
||||
return this->width == other.width && this->height == other.height;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -211,8 +211,8 @@ struct Rect {
|
||||
[[nodiscard]] inline Rect WithWidth(int width, bool end) const
|
||||
{
|
||||
return end
|
||||
? Rect {this->right - width + 1, this->top, this->right, this->bottom}
|
||||
: Rect {this->left, this->top, this->left + width - 1, this->bottom};
|
||||
? this->WithX(this->right - width + 1, this->right)
|
||||
: this->WithX(this->left, this->left + width - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,21 +224,21 @@ struct Rect {
|
||||
[[nodiscard]] inline Rect Indent(int indent, bool end) const
|
||||
{
|
||||
return end
|
||||
? Rect {this->left, this->top, this->right - indent, this->bottom}
|
||||
: Rect {this->left + indent, this->top, this->right, this->bottom};
|
||||
? this->WithX(this->left, this->right - indent)
|
||||
: this->WithX(this->left + indent, this->right);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy Rect and set its height.
|
||||
* @param width height in pixels for new Rect.
|
||||
* @param height height in pixels for new Rect.
|
||||
* @param end if set, set height at end of Rect, i.e. at bottom.
|
||||
* @return the new resized Rect.
|
||||
*/
|
||||
[[nodiscard]] inline Rect WithHeight(int height, bool end = false) const
|
||||
{
|
||||
return end
|
||||
? Rect {this->left, this->bottom - height + 1, this->right, this->bottom}
|
||||
: Rect {this->left, this->top, this->right, this->top + height - 1};
|
||||
? this->WithY(this->bottom - height + 1, this->bottom)
|
||||
: this->WithY(this->top, this->top + height - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -253,17 +253,45 @@ struct Rect {
|
||||
}
|
||||
|
||||
/**
|
||||
* Centre a dimension within this Rect.
|
||||
* @param width The horizontal dimension.
|
||||
* Centre a vertical dimension within this Rect.
|
||||
* @param height The vertical dimension.
|
||||
* @return the new resized Rect.
|
||||
*/
|
||||
[[nodiscard]] inline Rect CentreTo(int width, int height) const
|
||||
[[nodiscard]] inline Rect CentreToHeight(int height) const
|
||||
{
|
||||
int new_left = CentreBounds(this->left, this->right, width);
|
||||
int new_right = CentreBounds(this->top, this->bottom, height);
|
||||
return {new_left, new_right, new_left + width, new_right + height};
|
||||
int new_top = CentreBounds(this->top, this->bottom, height);
|
||||
return {this->left, new_top, this->right, new_top + height - 1};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Rect, replacing the left and right coordiates.
|
||||
* @param new_left New left coordinate.
|
||||
* @param new_right New right coordinate.
|
||||
* @return The new Rect.
|
||||
*/
|
||||
[[nodiscard]] inline Rect WithX(int new_left, int new_right) const { return {new_left, this->top, new_right, this->bottom}; }
|
||||
|
||||
/**
|
||||
* Create a new Rect, replacing the top and bottom coordiates.
|
||||
* @param new_top New top coordinate.
|
||||
* @param new_bottom New bottom coordinate.
|
||||
* @return The new Rect.
|
||||
*/
|
||||
[[nodiscard]] inline Rect WithY(int new_top, int new_bottom) const { return {this->left, new_top, this->right, new_bottom}; }
|
||||
|
||||
/**
|
||||
* Create a new Rect, replacing the left and right coordiates.
|
||||
* @param other Rect containing the new left and right coordinates.
|
||||
* @return The new Rect.
|
||||
*/
|
||||
[[nodiscard]] inline Rect WithX(const Rect &other) const { return this->WithX(other.left, other.right); }
|
||||
|
||||
/**
|
||||
* Create a new Rect, replacing the top and bottom coordiates.
|
||||
* @param other Rect containing the new top and bottom coordinates.
|
||||
* @return The new Rect.
|
||||
*/
|
||||
[[nodiscard]] inline Rect WithY(const Rect &other) const { return this->WithY(other.top, other.bottom); }
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file smallstack_type.hpp Minimal stack that uses a pool to avoid pointers and doesn't allocate any heap memory if there is only one valid item. */
|
||||
|
||||
#ifndef SMALLSTACK_TYPE_HPP
|
||||
#define SMALLSTACK_TYPE_HPP
|
||||
|
||||
/**
|
||||
* A simplified pool which stores values instead of pointers and doesn't
|
||||
* redefine operator new/delete. It also never zeroes memory and always reuses
|
||||
* it.
|
||||
*/
|
||||
template <typename Titem, typename Tindex, Tindex Tgrowth_step, Tindex Tmax_size>
|
||||
class SimplePool {
|
||||
public:
|
||||
inline SimplePool() : first_unused(0), first_free(0) {}
|
||||
|
||||
/**
|
||||
* Get the item at position index.
|
||||
* @return Item at index.
|
||||
*/
|
||||
inline Titem &Get(Tindex index) { return this->data[index]; }
|
||||
|
||||
/**
|
||||
* Create a new item and return its index.
|
||||
* @return Index of new item.
|
||||
*/
|
||||
inline Tindex Create()
|
||||
{
|
||||
Tindex index = this->FindFirstFree();
|
||||
if (index < Tmax_size) {
|
||||
this->data[index].valid = true;
|
||||
this->first_free = index + 1;
|
||||
this->first_unused = std::max(this->first_unused, this->first_free);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy (or rather invalidate) the item at the given index.
|
||||
* @param index Index of item to be destroyed.
|
||||
*/
|
||||
inline void Destroy(Tindex index)
|
||||
{
|
||||
this->data[index].valid = false;
|
||||
this->first_free = std::min(this->first_free, index);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
inline Tindex FindFirstFree()
|
||||
{
|
||||
Tindex index = this->first_free;
|
||||
for (; index < this->first_unused; index++) {
|
||||
if (!this->data[index].valid) return index;
|
||||
}
|
||||
|
||||
if (index >= this->data.size() && index < Tmax_size) {
|
||||
this->data.resize(index + 1);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
struct SimplePoolPoolItem : public Titem {
|
||||
bool valid;
|
||||
};
|
||||
|
||||
Tindex first_unused;
|
||||
Tindex first_free;
|
||||
|
||||
std::vector<SimplePoolPoolItem> data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for SmallStack. We cannot add this into SmallStack itself as
|
||||
* certain compilers don't like it.
|
||||
*/
|
||||
template <typename Titem, typename Tindex>
|
||||
struct SmallStackItem {
|
||||
Tindex next; ///< Pool index of next item.
|
||||
Titem value; ///< Value of current item.
|
||||
|
||||
/**
|
||||
* Create a new item.
|
||||
* @param value Value of the item.
|
||||
* @param next Next item in the stack.
|
||||
*/
|
||||
inline SmallStackItem(const Titem &value, Tindex next) :
|
||||
next(next), value(value) {}
|
||||
SmallStackItem() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* Minimal stack that uses a pool to avoid pointers. It has some peculiar
|
||||
* properties that make it useful for passing around lists of IDs but not much
|
||||
* else:
|
||||
* 1. It always includes an invalid item as bottom.
|
||||
* 2. It doesn't have a deep copy operation but uses smart pointers instead.
|
||||
* Every copy is thus implicitly shared.
|
||||
* 3. Its items are immutable.
|
||||
* 4. Due to 2. and 3. memory management can be done by "branch counting".
|
||||
* Whenever you copy a smallstack, the first item on the heap increases its
|
||||
* branch_count, signifying that there are multiple items "in front" of it.
|
||||
* When deleting a stack items are deleted up to the point where
|
||||
* branch_count > 0.
|
||||
* 5. You can choose your own index type, so that you can align it with your
|
||||
* value type. E.G. value types of 16 bits length like to be combined with
|
||||
* index types of the same length.
|
||||
* @tparam Titem Value type to be used.
|
||||
* @tparam Tindex Index type to use for the pool.
|
||||
* @tparam Tinvalid_value Value to construct invalid item to keep at the bottom of each stack.
|
||||
* @tparam Tgrowth_step Growth step for pool.
|
||||
* @tparam Tmax_size Maximum size for pool.
|
||||
*/
|
||||
template <typename Titem, typename Tindex, auto Tinvalid_value, Tindex Tgrowth_step, Tindex Tmax_size>
|
||||
class SmallStack : public SmallStackItem<Titem, Tindex> {
|
||||
public:
|
||||
static constexpr Titem Tinvalid{Tinvalid_value};
|
||||
|
||||
typedef SmallStackItem<Titem, Tindex> Item;
|
||||
|
||||
/**
|
||||
* SmallStack item that can be kept in a pool.
|
||||
*/
|
||||
struct PooledSmallStack : public Item {
|
||||
Tindex branch_count; ///< Number of branches in the tree structure this item is parent of
|
||||
};
|
||||
|
||||
typedef SimplePool<PooledSmallStack, Tindex, Tgrowth_step, Tmax_size> SmallStackPool;
|
||||
|
||||
/**
|
||||
* Constructor for a stack with one or two items in it.
|
||||
* @param value Initial item. If not missing or Tinvalid there will be Tinvalid below it.
|
||||
*/
|
||||
inline SmallStack(const Titem &value = Tinvalid) : Item(value, Tmax_size) {}
|
||||
|
||||
/**
|
||||
* Remove the head of stack and all other items members that are unique to it.
|
||||
*/
|
||||
inline ~SmallStack()
|
||||
{
|
||||
while (this->next != Tmax_size) this->Pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shallow copy the stack, marking the first item as branched.
|
||||
* @param other Stack to copy from
|
||||
*/
|
||||
inline SmallStack(const SmallStack &other) : Item(other) { this->Branch(); }
|
||||
|
||||
/**
|
||||
* Shallow copy the stack, marking the first item as branched.
|
||||
* @param other Stack to copy from
|
||||
* @return This smallstack.
|
||||
*/
|
||||
inline SmallStack &operator=(const SmallStack &other)
|
||||
{
|
||||
if (this == &other) return *this;
|
||||
while (this->next != Tmax_size) this->Pop();
|
||||
this->next = other.next;
|
||||
this->value = other.value;
|
||||
/* Deleting and branching are independent operations, so it's fine to
|
||||
* acquire separate locks for them. */
|
||||
this->Branch();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a new item onto the stack if there is still space in the
|
||||
* underlying pool. Otherwise the topmost item's value gets overwritten.
|
||||
* @param item Item to be pushed.
|
||||
*/
|
||||
inline void Push(const Titem &item)
|
||||
{
|
||||
if (this->value != Tinvalid) {
|
||||
Tindex new_item = SmallStack::GetPool().Create();
|
||||
if (new_item != Tmax_size) {
|
||||
PooledSmallStack &pushed = SmallStack::GetPool().Get(new_item);
|
||||
pushed.value = this->value;
|
||||
pushed.next = this->next;
|
||||
pushed.branch_count = 0;
|
||||
this->next = new_item;
|
||||
}
|
||||
}
|
||||
this->value = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop an item from the stack.
|
||||
* @return Current top of stack.
|
||||
*/
|
||||
inline Titem Pop()
|
||||
{
|
||||
Titem ret = this->value;
|
||||
if (this->next == Tmax_size) {
|
||||
this->value = Tinvalid;
|
||||
} else {
|
||||
PooledSmallStack &popped = SmallStack::GetPool().Get(this->next);
|
||||
this->value = popped.value;
|
||||
if (popped.branch_count == 0) {
|
||||
SmallStack::GetPool().Destroy(this->next);
|
||||
} else {
|
||||
--popped.branch_count;
|
||||
if (popped.next != Tmax_size) {
|
||||
++(SmallStack::GetPool().Get(popped.next).branch_count);
|
||||
}
|
||||
}
|
||||
/* Accessing popped here is no problem as the pool will only set
|
||||
* the validity flag, not actually delete the item, on Destroy(). */
|
||||
this->next = popped.next;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the stack is empty.
|
||||
* @return If the stack is empty.
|
||||
*/
|
||||
inline bool IsEmpty() const
|
||||
{
|
||||
return this->value == Tinvalid && this->next == Tmax_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given item is contained in the stack.
|
||||
* @param item Item to look for.
|
||||
* @return If the item is in the stack.
|
||||
*/
|
||||
inline bool Contains(const Titem &item) const
|
||||
{
|
||||
if (item == Tinvalid || item == this->value) return true;
|
||||
if (this->next != Tmax_size) {
|
||||
const SmallStack *in_list = this;
|
||||
do {
|
||||
in_list = static_cast<const SmallStack *>(
|
||||
static_cast<const Item *>(&SmallStack::GetPool().Get(in_list->next)));
|
||||
if (in_list->value == item) return true;
|
||||
} while (in_list->next != Tmax_size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
static SmallStackPool &GetPool()
|
||||
{
|
||||
static SmallStackPool pool;
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a branch in the pool if necessary.
|
||||
*/
|
||||
inline void Branch()
|
||||
{
|
||||
if (this->next != Tmax_size) {
|
||||
++(SmallStack::GetPool().Get(this->next).branch_count);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -158,4 +158,31 @@ namespace StrongType {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of std::hash for StrongType::Typedef.
|
||||
*
|
||||
* This specialization of std::hash allows hashing of StrongType::Typedef instances
|
||||
* by leveraging the hash of the base type.
|
||||
*
|
||||
* Example Usage:
|
||||
* using MyType = StrongType::Typedef<int, struct MyTypeTag>;
|
||||
* std::unordered_map<MyType, std::string> my_map;
|
||||
*
|
||||
* @tparam TBaseType The underlying type of the StrongType::Typedef.
|
||||
* @tparam TProperties Additional properties for the StrongType::Typedef.
|
||||
*/
|
||||
template <typename TBaseType, typename... TProperties>
|
||||
struct std::hash<StrongType::Typedef<TBaseType, TProperties...>> {
|
||||
/**
|
||||
* Computes the hash value for a StrongType::Typedef instance.
|
||||
*
|
||||
* @param t The StrongType::Typedef instance to hash.
|
||||
* @return The hash value of the base type of t.
|
||||
*/
|
||||
std::size_t operator()(const StrongType::Typedef<TBaseType, TProperties...> &t) const noexcept
|
||||
{
|
||||
return std::hash<TBaseType>()(t.base());
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* STRONG_TYPEDEF_TYPE_HPP */
|
||||
|
||||
+1
-1
@@ -173,7 +173,7 @@ struct SetDateWindow : Window {
|
||||
};
|
||||
|
||||
/** Widgets for the date setting window. */
|
||||
static constexpr NWidgetPart _nested_set_date_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_set_date_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
|
||||
NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_DATE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
|
||||
CommandCost CmdRenameDepot(DoCommandFlags flags, DepotID depot_id, const std::string &text);
|
||||
|
||||
DEF_CMD_TRAIT(CMD_RENAME_DEPOT, CmdRenameDepot, {}, CMDT_OTHER_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_RENAME_DEPOT, CmdRenameDepot, {}, CommandType::OtherManagement)
|
||||
|
||||
void CcCloneVehicle(Commands cmd, const CommandCost &result, VehicleID veh_id);
|
||||
|
||||
|
||||
+7
-7
@@ -17,7 +17,7 @@
|
||||
#include "viewport_func.h"
|
||||
#include "command_func.h"
|
||||
#include "depot_base.h"
|
||||
#include "spritecache.h"
|
||||
#include "spritecache_type.h"
|
||||
#include "strings_func.h"
|
||||
#include "sound_func.h"
|
||||
#include "vehicle_func.h"
|
||||
@@ -47,7 +47,7 @@
|
||||
*/
|
||||
|
||||
/** Nested widget definition for train depots. */
|
||||
static constexpr NWidgetPart _nested_train_depot_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_train_depot_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_D_SHOW_RENAME), SetAspect(WidgetDimensions::ASPECT_RENAME), // rename button
|
||||
@@ -229,7 +229,7 @@ void InitDepotWindowBlockSizes()
|
||||
if (!e->IsEnabled()) continue;
|
||||
|
||||
uint w = TRAININFO_DEFAULT_VEHICLE_WIDTH;
|
||||
if (e->GetGRF() != nullptr && IsCustomVehicleSpriteNum(e->u.rail.image_index)) {
|
||||
if (e->GetGRF() != nullptr && IsCustomVehicleSpriteNum(e->VehInfo<RailVehicleInfo>().image_index)) {
|
||||
w = e->GetGRF()->traininfo_vehicle_width;
|
||||
if (w != VEHICLEINFO_FULL_VEHICLE_WIDTH) {
|
||||
/* Hopeless.
|
||||
@@ -260,7 +260,7 @@ struct DepotWindow : Window {
|
||||
VehicleType type = VEH_INVALID;
|
||||
bool generate_list = true;
|
||||
bool check_unitnumber_digits = true;
|
||||
WidgetID hovered_widget = -1; ///< Index of the widget being hovered during drag/drop. -1 if no drag is in progress.
|
||||
WidgetID hovered_widget = INVALID_WIDGET; ///< Index of the widget being hovered during drag/drop. \c INVALID_WIDGET if no drag is in progress.
|
||||
VehicleList vehicle_list{};
|
||||
VehicleList wagon_list{};
|
||||
uint unitnumber_digits = 2;
|
||||
@@ -1001,10 +1001,10 @@ struct DepotWindow : Window {
|
||||
this->vehicle_over = VehicleID::Invalid();
|
||||
this->SetWidgetDirty(WID_D_MATRIX);
|
||||
|
||||
if (this->hovered_widget != -1) {
|
||||
if (this->hovered_widget != INVALID_WIDGET) {
|
||||
this->SetWidgetLoweredState(this->hovered_widget, false);
|
||||
this->SetWidgetDirty(this->hovered_widget);
|
||||
this->hovered_widget = -1;
|
||||
this->hovered_widget = INVALID_WIDGET;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1116,7 +1116,7 @@ struct DepotWindow : Window {
|
||||
this->SetDirty();
|
||||
break;
|
||||
}
|
||||
this->hovered_widget = -1;
|
||||
this->hovered_widget = INVALID_WIDGET;
|
||||
_cursor.vehchain = false;
|
||||
}
|
||||
|
||||
|
||||
+29
-33
@@ -98,7 +98,7 @@ static TileIndex GetOtherAqueductEnd(TileIndex tile_from, TileIndex *tile_to = n
|
||||
|
||||
/** Toolbar window for constructing water infrastructure. */
|
||||
struct BuildDocksToolbarWindow : Window {
|
||||
DockToolbarWidgets last_clicked_widget = WID_DT_INVALID; ///< Contains the last widget that has been clicked on this toolbar.
|
||||
WidgetID last_clicked_widget = INVALID_WIDGET; ///< Contains the last widget that has been clicked on this toolbar.
|
||||
|
||||
BuildDocksToolbarWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc)
|
||||
{
|
||||
@@ -189,7 +189,7 @@ struct BuildDocksToolbarWindow : Window {
|
||||
|
||||
default: return;
|
||||
}
|
||||
this->last_clicked_widget = (DockToolbarWidgets)widget;
|
||||
this->last_clicked_widget = widget;
|
||||
}
|
||||
|
||||
void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
|
||||
@@ -250,6 +250,11 @@ struct BuildDocksToolbarWindow : Window {
|
||||
VpSelectTilesWithMethod(pt.x, pt.y, select_method);
|
||||
}
|
||||
|
||||
Point OnInitialPosition(int16_t sm_width, [[maybe_unused]] int16_t sm_height, [[maybe_unused]] int window_number) override
|
||||
{
|
||||
return AlignInitialConstructionToolbar(sm_width);
|
||||
}
|
||||
|
||||
void OnPlaceMouseUp([[maybe_unused]] ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, [[maybe_unused]] Point pt, TileIndex start_tile, TileIndex end_tile) override
|
||||
{
|
||||
if (pt.x != -1) {
|
||||
@@ -259,13 +264,13 @@ struct BuildDocksToolbarWindow : Window {
|
||||
break;
|
||||
case DDSP_CREATE_WATER:
|
||||
if (_game_mode == GM_EDITOR) {
|
||||
Command<CMD_BUILD_CANAL>::Post(STR_ERROR_CAN_T_BUILD_CANALS, CcPlaySound_CONSTRUCTION_WATER, end_tile, start_tile, _ctrl_pressed ? WATER_CLASS_SEA : WATER_CLASS_CANAL, false);
|
||||
Command<CMD_BUILD_CANAL>::Post(STR_ERROR_CAN_T_BUILD_CANALS, CcPlaySound_CONSTRUCTION_WATER, end_tile, start_tile, _ctrl_pressed ? WaterClass::Sea : WaterClass::Canal, false);
|
||||
} else {
|
||||
Command<CMD_BUILD_CANAL>::Post(STR_ERROR_CAN_T_BUILD_CANALS, CcPlaySound_CONSTRUCTION_WATER, end_tile, start_tile, WATER_CLASS_CANAL, _ctrl_pressed);
|
||||
Command<CMD_BUILD_CANAL>::Post(STR_ERROR_CAN_T_BUILD_CANALS, CcPlaySound_CONSTRUCTION_WATER, end_tile, start_tile, WaterClass::Canal, _ctrl_pressed);
|
||||
}
|
||||
break;
|
||||
case DDSP_CREATE_RIVER:
|
||||
Command<CMD_BUILD_CANAL>::Post(STR_ERROR_CAN_T_PLACE_RIVERS, CcPlaySound_CONSTRUCTION_WATER, end_tile, start_tile, WATER_CLASS_RIVER, _ctrl_pressed);
|
||||
Command<CMD_BUILD_CANAL>::Post(STR_ERROR_CAN_T_PLACE_RIVERS, CcPlaySound_CONSTRUCTION_WATER, end_tile, start_tile, WaterClass::River, _ctrl_pressed);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
@@ -333,7 +338,7 @@ struct BuildDocksToolbarWindow : Window {
|
||||
* Nested widget parts of docks toolbar, game version.
|
||||
* Position of #WID_DT_RIVER widget has changed.
|
||||
*/
|
||||
static constexpr NWidgetPart _nested_build_docks_toolbar_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_build_docks_toolbar_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_WATERWAYS_TOOLBAR_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
@@ -352,7 +357,7 @@ static constexpr NWidgetPart _nested_build_docks_toolbar_widgets[] = {
|
||||
};
|
||||
|
||||
static WindowDesc _build_docks_toolbar_desc(
|
||||
WDP_ALIGN_TOOLBAR, "toolbar_water", 0, 0,
|
||||
WDP_MANUAL, "toolbar_water", 0, 0,
|
||||
WC_BUILD_TOOLBAR, WC_NONE,
|
||||
WindowDefaultFlag::Construction,
|
||||
_nested_build_docks_toolbar_widgets,
|
||||
@@ -378,7 +383,7 @@ Window *ShowBuildDocksToolbar()
|
||||
* Nested widget parts of docks toolbar, scenario editor version.
|
||||
* Positions of #WID_DT_DEPOT, #WID_DT_STATION, and #WID_DT_BUOY widgets have changed.
|
||||
*/
|
||||
static constexpr NWidgetPart _nested_build_docks_scen_toolbar_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_build_docks_scen_toolbar_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_WATERWAYS_TOOLBAR_CAPTION_SE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
@@ -412,21 +417,12 @@ Window *ShowBuildDocksScenToolbar()
|
||||
return AllocateWindowDescFront<BuildDocksToolbarWindow>(_build_docks_scen_toolbar_desc, TRANSPORT_WATER);
|
||||
}
|
||||
|
||||
/** Widget numbers of the build-dock GUI. */
|
||||
enum BuildDockStationWidgets {
|
||||
BDSW_BACKGROUND, ///< Background panel.
|
||||
BDSW_LT_OFF, ///< 'Off' button of coverage high light.
|
||||
BDSW_LT_ON, ///< 'On' button of coverage high light.
|
||||
BDSW_INFO, ///< 'Coverage highlight' label.
|
||||
BDSW_ACCEPTANCE, ///< Acceptance info.
|
||||
};
|
||||
|
||||
struct BuildDocksStationWindow : public PickerWindowBase {
|
||||
public:
|
||||
BuildDocksStationWindow(WindowDesc &desc, Window *parent) : PickerWindowBase(desc, parent)
|
||||
{
|
||||
this->InitNested(TRANSPORT_WATER);
|
||||
this->LowerWidget(_settings_client.gui.station_show_coverage + BDSW_LT_OFF);
|
||||
this->LowerWidget(_settings_client.gui.station_show_coverage + WID_BDSW_LT_OFF);
|
||||
}
|
||||
|
||||
void Close([[maybe_unused]] int data = 0) override
|
||||
@@ -448,7 +444,7 @@ public:
|
||||
}
|
||||
|
||||
/* strings such as 'Size' and 'Coverage Area' */
|
||||
Rect r = this->GetWidget<NWidgetBase>(BDSW_ACCEPTANCE)->GetCurrentRect();
|
||||
Rect r = this->GetWidget<NWidgetBase>(WID_BDSW_ACCEPTANCE)->GetCurrentRect();
|
||||
const int bottom = r.bottom;
|
||||
r.bottom = INT_MAX; // Allow overflow as we want to know the required height.
|
||||
r.top = DrawStationCoverageAreaText(r, SCT_ALL, rad, false) + WidgetDimensions::scaled.vsep_normal;
|
||||
@@ -464,11 +460,11 @@ public:
|
||||
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
|
||||
{
|
||||
switch (widget) {
|
||||
case BDSW_LT_OFF:
|
||||
case BDSW_LT_ON:
|
||||
this->RaiseWidget(_settings_client.gui.station_show_coverage + BDSW_LT_OFF);
|
||||
_settings_client.gui.station_show_coverage = (widget != BDSW_LT_OFF);
|
||||
this->LowerWidget(_settings_client.gui.station_show_coverage + BDSW_LT_OFF);
|
||||
case WID_BDSW_LT_OFF:
|
||||
case WID_BDSW_LT_ON:
|
||||
this->RaiseWidget(_settings_client.gui.station_show_coverage + WID_BDSW_LT_OFF);
|
||||
_settings_client.gui.station_show_coverage = (widget != WID_BDSW_LT_OFF);
|
||||
this->LowerWidget(_settings_client.gui.station_show_coverage + WID_BDSW_LT_OFF);
|
||||
SndClickBeep();
|
||||
this->SetDirty();
|
||||
SetViewportCatchmentStation(nullptr, true);
|
||||
@@ -487,21 +483,21 @@ public:
|
||||
};
|
||||
|
||||
/** Nested widget parts of a build dock station window. */
|
||||
static constexpr NWidgetPart _nested_build_dock_station_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_build_dock_station_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_STATION_BUILD_DOCK_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BDSW_BACKGROUND),
|
||||
NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BDSW_BACKGROUND),
|
||||
NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, 0), SetPadding(WidgetDimensions::unscaled.picker),
|
||||
NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_picker, 0),
|
||||
NWidget(WWT_LABEL, INVALID_COLOUR, BDSW_INFO), SetStringTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE), SetFill(1, 0),
|
||||
NWidget(WWT_LABEL, INVALID_COLOUR, WID_BDSW_INFO), SetStringTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE), SetFill(1, 0),
|
||||
NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize), SetPIP(14, 0, 14),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, BDSW_LT_OFF), SetMinimalSize(60, 12), SetFill(1, 0), SetStringTip(STR_STATION_BUILD_COVERAGE_OFF, STR_STATION_BUILD_COVERAGE_AREA_OFF_TOOLTIP),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, BDSW_LT_ON), SetMinimalSize(60, 12), SetFill(1, 0), SetStringTip(STR_STATION_BUILD_COVERAGE_ON, STR_STATION_BUILD_COVERAGE_AREA_ON_TOOLTIP),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BDSW_LT_OFF), SetMinimalSize(60, 12), SetFill(1, 0), SetStringTip(STR_STATION_BUILD_COVERAGE_OFF, STR_STATION_BUILD_COVERAGE_AREA_OFF_TOOLTIP),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BDSW_LT_ON), SetMinimalSize(60, 12), SetFill(1, 0), SetStringTip(STR_STATION_BUILD_COVERAGE_ON, STR_STATION_BUILD_COVERAGE_AREA_ON_TOOLTIP),
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
NWidget(WWT_EMPTY, INVALID_COLOUR, BDSW_ACCEPTANCE), SetResize(0, 1), SetMinimalTextLines(2, WidgetDimensions::unscaled.vsep_normal),
|
||||
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BDSW_ACCEPTANCE), SetResize(0, 1), SetMinimalTextLines(2, WidgetDimensions::unscaled.vsep_normal),
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
};
|
||||
@@ -564,8 +560,8 @@ public:
|
||||
int y = (ir.Height() - ScaleSpriteTrad(64)) / 2;
|
||||
int x1 = ScaleSpriteTrad(63);
|
||||
int x2 = ScaleSpriteTrad(31);
|
||||
DrawShipDepotSprite(x + (axis == AXIS_X ? x1 : x2), y + ScaleSpriteTrad(17), axis, DEPOT_PART_NORTH);
|
||||
DrawShipDepotSprite(x + (axis == AXIS_X ? x2 : x1), y + ScaleSpriteTrad(33), axis, DEPOT_PART_SOUTH);
|
||||
DrawShipDepotSprite(x + (axis == AXIS_X ? x1 : x2), y + ScaleSpriteTrad(17), axis, DepotPart::North);
|
||||
DrawShipDepotSprite(x + (axis == AXIS_X ? x2 : x1), y + ScaleSpriteTrad(33), axis, DepotPart::South);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -588,7 +584,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr NWidgetPart _nested_build_docks_depot_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_build_docks_depot_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_DEPOT_BUILD_SHIP_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
|
||||
+3
-2
@@ -145,11 +145,12 @@ bool DriverFactoryBase::SelectDriverImpl(const std::string &name, Driver::Type t
|
||||
|
||||
/* Keep old driver in case we need to switch back, or may still need to process an OS callback. */
|
||||
auto oldd = std::move(GetActiveDriver(type));
|
||||
GetActiveDriver(type) = d->CreateInstance();
|
||||
auto newd = d->CreateInstance();
|
||||
|
||||
auto err = GetActiveDriver(type)->Start({});
|
||||
auto err = newd->Start({});
|
||||
if (!err) {
|
||||
Debug(driver, 1, "Successfully probed {} driver '{}'", GetDriverTypeName(type), d->name);
|
||||
GetActiveDriver(type) = std::move(newd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+43
-40
@@ -8,6 +8,7 @@
|
||||
/** @file dropdown.cpp Implementation of the dropdown widget. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "core/backup_type.hpp"
|
||||
#include "dropdown_type.h"
|
||||
#include "dropdown_func.h"
|
||||
#include "strings_func.h"
|
||||
@@ -56,7 +57,7 @@ std::unique_ptr<DropDownListItem> MakeDropDownListCheckedItem(bool checked, Stri
|
||||
return std::make_unique<DropDownListCheckedItem>(indent, checked, GetString(str), value, masked, shaded);
|
||||
}
|
||||
|
||||
static constexpr NWidgetPart _nested_dropdown_menu_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_dropdown_menu_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_PANEL, COLOUR_END, WID_DM_ITEMS), SetScrollbar(WID_DM_SCROLL), EndContainer(),
|
||||
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_DM_SHOW_SCROLL),
|
||||
@@ -81,8 +82,7 @@ struct DropdownWindow : Window {
|
||||
int selected_click_result = -1; ///< Click result value, from the OnClick handler of the selected item.
|
||||
uint8_t click_delay = 0; ///< Timer to delay selection.
|
||||
bool drag_mode = true;
|
||||
bool instant_close = false; ///< Close the window when the mouse button is raised.
|
||||
bool persist = false; ///< Persist dropdown menu.
|
||||
DropDownOptions options; ///< Options for this drop down menu.
|
||||
int scrolling = 0; ///< If non-zero, auto-scroll the item list (one time).
|
||||
Point position{}; ///< Position of the topleft corner of the window.
|
||||
Scrollbar *vscroll = nullptr;
|
||||
@@ -96,18 +96,16 @@ struct DropdownWindow : Window {
|
||||
* @param selected Initial selected result of the list.
|
||||
* @param button Widget of the parent window doing the dropdown.
|
||||
* @param wi_rect Rect of the button that opened the dropdown.
|
||||
* @param instant_close Close the window when the mouse button is raised.
|
||||
* @param wi_colour Colour of the parent widget.
|
||||
* @param persist Dropdown menu will persist.
|
||||
* @param options Drop Down options for this menu.
|
||||
*/
|
||||
DropdownWindow(Window *parent, DropDownList &&list, int selected, WidgetID button, const Rect wi_rect, bool instant_close, Colours wi_colour, bool persist)
|
||||
DropdownWindow(Window *parent, DropDownList &&list, int selected, WidgetID button, const Rect wi_rect, Colours wi_colour, DropDownOptions options)
|
||||
: Window(_dropdown_desc)
|
||||
, parent_button(button)
|
||||
, wi_rect(wi_rect)
|
||||
, list(std::move(list))
|
||||
, selected_result(selected)
|
||||
, instant_close(instant_close)
|
||||
, persist(persist)
|
||||
, options(options)
|
||||
{
|
||||
assert(!this->list.empty());
|
||||
|
||||
@@ -133,7 +131,7 @@ struct DropdownWindow : Window {
|
||||
Point pt = _cursor.pos;
|
||||
pt.x -= this->parent->left;
|
||||
pt.y -= this->parent->top;
|
||||
this->parent->OnDropdownClose(pt, this->parent_button, this->selected_result, this->selected_click_result, this->instant_close);
|
||||
this->parent->OnDropdownClose(pt, this->parent_button, this->selected_result, this->selected_click_result, this->options.Test(DropDownOption::InstantClose));
|
||||
|
||||
/* Set flag on parent widget to indicate that we have just closed. */
|
||||
NWidgetCore *nwc = this->parent->GetWidget<NWidgetCore>(this->parent_button);
|
||||
@@ -143,7 +141,7 @@ struct DropdownWindow : Window {
|
||||
void OnFocusLost(bool closing) override
|
||||
{
|
||||
if (!closing) {
|
||||
this->instant_close = false;
|
||||
this->options.Reset(DropDownOption::InstantClose);
|
||||
this->Close();
|
||||
}
|
||||
}
|
||||
@@ -208,8 +206,9 @@ struct DropdownWindow : Window {
|
||||
this->GetWidget<NWidgetStacked>(WID_DM_SHOW_SCROLL)->SetDisplayedPlane(list_dim.height > widget_dim.height ? 0 : SZSP_NONE);
|
||||
|
||||
/* Capacity is the average number of items visible */
|
||||
this->vscroll->SetCapacity((widget_dim.height - WidgetDimensions::scaled.dropdownlist.Vertical()) * this->list.size() / list_dim.height);
|
||||
this->vscroll->SetCount(this->list.size());
|
||||
this->vscroll->SetCapacity(widget_dim.height - WidgetDimensions::scaled.dropdownlist.Vertical());
|
||||
this->vscroll->SetStepSize(list_dim.height / this->list.size());
|
||||
this->vscroll->SetCount(list_dim.height);
|
||||
|
||||
/* If the dropdown is positioned above the parent widget, start selection at the bottom. */
|
||||
if (this->position.y < button_rect.top && list_dim.height > widget_dim.height) this->vscroll->UpdatePosition(INT_MAX);
|
||||
@@ -236,23 +235,22 @@ struct DropdownWindow : Window {
|
||||
if (GetWidgetFromPos(this, _cursor.pos.x - this->left, _cursor.pos.y - this->top) < 0) return false;
|
||||
|
||||
const Rect &r = this->GetWidget<NWidgetBase>(WID_DM_ITEMS)->GetCurrentRect().Shrink(WidgetDimensions::scaled.dropdownlist).Shrink(WidgetDimensions::scaled.dropdowntext, RectPadding::zero);
|
||||
int y = _cursor.pos.y - this->top - r.top;
|
||||
int pos = this->vscroll->GetPosition();
|
||||
int click_y = _cursor.pos.y - this->top - r.top;
|
||||
int y = -this->vscroll->GetPosition();
|
||||
int y_end = r.Height();
|
||||
|
||||
for (const auto &item : this->list) {
|
||||
/* Skip items that are scrolled up */
|
||||
if (--pos >= 0) continue;
|
||||
|
||||
int item_height = item->Height();
|
||||
|
||||
if (y < item_height) {
|
||||
/* Skip items that are scrolled up */
|
||||
if (y > y_end) break;
|
||||
if (click_y >= y && click_y < y + item_height) {
|
||||
if (item->masked || !item->Selectable()) return false;
|
||||
result = item->result;
|
||||
click_result = item->OnClick({r.left, 0, r.right, item_height - 1}, {_cursor.pos.x - this->left, y});
|
||||
click_result = item->OnClick(r.WithY(0, item_height - 1), {_cursor.pos.x - this->left, click_y - y});
|
||||
return true;
|
||||
}
|
||||
|
||||
y -= item_height;
|
||||
y += item_height;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -265,16 +263,25 @@ struct DropdownWindow : Window {
|
||||
Colours colour = this->GetWidget<NWidgetCore>(widget)->colour;
|
||||
|
||||
Rect ir = r.Shrink(WidgetDimensions::scaled.dropdownlist);
|
||||
int y = ir.top;
|
||||
int pos = this->vscroll->GetPosition();
|
||||
|
||||
/* Setup a clipping rectangle... */
|
||||
DrawPixelInfo tmp_dpi;
|
||||
if (!FillDrawPixelInfo(&tmp_dpi, ir)) return;
|
||||
/* ...but keep coordinates relative to the window. */
|
||||
tmp_dpi.left += ir.left;
|
||||
tmp_dpi.top += ir.top;
|
||||
AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
|
||||
|
||||
int y = -this->vscroll->GetPosition();
|
||||
int y_end = ir.Height();
|
||||
|
||||
for (const auto &item : this->list) {
|
||||
int item_height = item->Height();
|
||||
|
||||
/* Skip items that are scrolled up */
|
||||
if (--pos >= 0) continue;
|
||||
|
||||
if (y + item_height - 1 <= ir.bottom) {
|
||||
Rect full{ir.left, y, ir.right, y + item_height - 1};
|
||||
if (y > y_end) break;
|
||||
if (y > -item_height) {
|
||||
Rect full = ir.Translate(0, y).WithHeight(item_height);
|
||||
|
||||
bool selected = (this->selected_result == item->result) && item->Selectable();
|
||||
if (selected) GfxFillRect(full, PC_BLACK);
|
||||
@@ -311,7 +318,7 @@ struct DropdownWindow : Window {
|
||||
if (this->click_delay != 0 && --this->click_delay == 0) {
|
||||
/* Close the dropdown, so it doesn't affect new window placement.
|
||||
* Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */
|
||||
if (!this->persist) this->Close();
|
||||
if (!this->options.Test(DropDownOption::Persist)) this->Close();
|
||||
this->parent->OnDropdownSelect(this->parent_button, this->selected_result, this->selected_click_result);
|
||||
return;
|
||||
}
|
||||
@@ -322,7 +329,7 @@ struct DropdownWindow : Window {
|
||||
if (!_left_button_clicked) {
|
||||
this->drag_mode = false;
|
||||
if (!this->GetDropDownItem(result, click_result)) {
|
||||
if (this->instant_close) this->Close();
|
||||
if (this->options.Test(DropDownOption::InstantClose)) this->Close();
|
||||
return;
|
||||
}
|
||||
this->click_delay = 2;
|
||||
@@ -390,14 +397,12 @@ Dimension GetDropDownListDimension(const DropDownList &list)
|
||||
* @param button The widget which is passed to Window::OnDropdownSelect and OnDropdownClose.
|
||||
* Unless you override those functions, this should be then widget index of the dropdown button.
|
||||
* @param wi_rect Coord of the parent drop down button, used to position the dropdown menu.
|
||||
* @param instant_close Set to true if releasing mouse button should close the
|
||||
* list regardless of where the cursor is.
|
||||
* @param persist Set if this dropdown should stay open after an option is selected.
|
||||
* @param options Drop Down options for this menu.
|
||||
*/
|
||||
void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, WidgetID button, Rect wi_rect, Colours wi_colour, bool instant_close, bool persist)
|
||||
void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, WidgetID button, Rect wi_rect, Colours wi_colour, DropDownOptions options)
|
||||
{
|
||||
CloseWindowByClass(WC_DROPDOWN_MENU);
|
||||
new DropdownWindow(w, std::move(list), selected, button, wi_rect, instant_close, wi_colour, persist);
|
||||
new DropdownWindow(w, std::move(list), selected, button, wi_rect, wi_colour, options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -408,11 +413,9 @@ void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, WidgetID b
|
||||
* @param button The widget within the parent window that is used to determine
|
||||
* the list's location.
|
||||
* @param width Override the minimum width determined by the selected widget and list contents.
|
||||
* @param instant_close Set to true if releasing mouse button should close the
|
||||
* list regardless of where the cursor is.
|
||||
* @param persist Set if this dropdown should stay open after an option is selected.
|
||||
* @param options Drop Down options for this menu.
|
||||
*/
|
||||
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, bool instant_close, bool persist)
|
||||
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, DropDownOptions options)
|
||||
{
|
||||
/* Handle the beep of the player's click. */
|
||||
SndClickBeep();
|
||||
@@ -438,7 +441,7 @@ void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID but
|
||||
}
|
||||
}
|
||||
|
||||
ShowDropDownListAt(w, std::move(list), selected, button, wi_rect, wi_colour, instant_close, persist);
|
||||
ShowDropDownListAt(w, std::move(list), selected, button, wi_rect, wi_colour, options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -464,5 +467,5 @@ void ShowDropDownMenu(Window *w, std::span<const StringID> strings, int selected
|
||||
++i;
|
||||
}
|
||||
|
||||
if (!list.empty()) ShowDropDownList(w, std::move(list), selected, button, width);
|
||||
if (!list.empty()) ShowDropDownList(w, std::move(list), selected, button, width, {});
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ public:
|
||||
PixelColour c2 = GetColourGradient(bg_colour, SHADE_LIGHTEST);
|
||||
|
||||
int mid = CentreBounds(full.top, full.bottom, 0);
|
||||
GfxFillRect(full.left, mid - WidgetDimensions::scaled.bevel.bottom, full.right, mid - 1, c1);
|
||||
GfxFillRect(full.left, mid, full.right, mid + WidgetDimensions::scaled.bevel.top - 1, c2);
|
||||
GfxFillRect(full.WithY(mid - WidgetDimensions::scaled.bevel.bottom, mid - 1), c1);
|
||||
GfxFillRect(full.WithY(mid, mid + WidgetDimensions::scaled.bevel.top - 1), c2);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -216,7 +216,7 @@ public:
|
||||
bool rtl = TEnd ^ (_current_text_dir == TD_RTL);
|
||||
int w = SETTING_BUTTON_WIDTH;
|
||||
|
||||
if (r.WithWidth(w, rtl).CentreTo(w, SETTING_BUTTON_HEIGHT).Contains(pt)) return this->click;
|
||||
if (r.WithWidth(w, rtl).CentreToHeight(SETTING_BUTTON_HEIGHT).Contains(pt)) return this->click;
|
||||
|
||||
return this->TBase::OnClick(r.Indent(w + WidgetDimensions::scaled.hsep_wide, rtl), pt);
|
||||
}
|
||||
@@ -226,7 +226,7 @@ public:
|
||||
bool rtl = TEnd ^ (_current_text_dir == TD_RTL);
|
||||
int w = SETTING_BUTTON_WIDTH;
|
||||
|
||||
Rect br = r.WithWidth(w, rtl).CentreTo(w, SETTING_BUTTON_HEIGHT);
|
||||
Rect br = r.WithWidth(w, rtl).CentreToHeight(SETTING_BUTTON_HEIGHT);
|
||||
DrawBoolButton(br.left, br.top, this->button_colour, this->background_colour, this->on, true);
|
||||
|
||||
this->TBase::Draw(full, r.Indent(w + WidgetDimensions::scaled.hsep_wide, rtl), sel, click_result, bg_colour);
|
||||
@@ -260,6 +260,32 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Drop down spacer component.
|
||||
* @tparam TBase Base component.
|
||||
* @tparam TEnd Position space at end if true, or start if false.
|
||||
*/
|
||||
template <class TBase, bool TEnd = false>
|
||||
class DropDownSpacer : public TBase {
|
||||
public:
|
||||
template <typename... Args>
|
||||
explicit DropDownSpacer(Args&&... args) : TBase(std::forward<Args>(args)...) {}
|
||||
|
||||
uint Width() const override { return WidgetDimensions::scaled.hsep_wide + this->TBase::Width(); }
|
||||
|
||||
int OnClick(const Rect &r, const Point &pt) const override
|
||||
{
|
||||
bool rtl = TEnd ^ (_current_text_dir == TD_RTL);
|
||||
return this->TBase::OnClick(r.Indent(WidgetDimensions::scaled.hsep_wide, rtl), pt);
|
||||
}
|
||||
|
||||
void Draw(const Rect &full, const Rect &r, bool sel, int click_result, Colours bg_colour) const override
|
||||
{
|
||||
bool rtl = TEnd ^ (_current_text_dir == TD_RTL);
|
||||
this->TBase::Draw(full, r.Indent(WidgetDimensions::scaled.hsep_wide, rtl), sel, click_result, bg_colour);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Drop down component that makes the item unselectable.
|
||||
* @tparam TBase Base component.
|
||||
|
||||
+9
-2
@@ -10,6 +10,7 @@
|
||||
#ifndef DROPDOWN_TYPE_H
|
||||
#define DROPDOWN_TYPE_H
|
||||
|
||||
#include "core/enum_type.hpp"
|
||||
#include "window_type.h"
|
||||
#include "gfx_func.h"
|
||||
#include "gfx_type.h"
|
||||
@@ -54,9 +55,15 @@ public:
|
||||
*/
|
||||
typedef std::vector<std::unique_ptr<const DropDownListItem>> DropDownList;
|
||||
|
||||
void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, WidgetID button, Rect wi_rect, Colours wi_colour, bool instant_close = false, bool persist = false);
|
||||
enum class DropDownOption : uint8_t {
|
||||
InstantClose, ///< Set if releasing mouse button should close the list regardless of where the cursor is.
|
||||
Persist, ///< Set if this dropdown should stay open after an option is selected.
|
||||
};
|
||||
using DropDownOptions = EnumBitSet<DropDownOption, uint8_t>;
|
||||
|
||||
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width = 0, bool instant_close = false, bool persist = false);
|
||||
void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, WidgetID button, Rect wi_rect, Colours wi_colour, DropDownOptions options = {});
|
||||
|
||||
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width = 0, DropDownOptions options = {});
|
||||
|
||||
Dimension GetDropDownListDimension(const DropDownList &list);
|
||||
|
||||
|
||||
+22
-20
@@ -1181,7 +1181,7 @@ CargoPayment::CargoPayment(Vehicle *front) :
|
||||
|
||||
CargoPayment::~CargoPayment()
|
||||
{
|
||||
if (this->CleaningPool()) return;
|
||||
if (CleaningPool()) return;
|
||||
|
||||
this->front->cargo_payment = nullptr;
|
||||
|
||||
@@ -1270,8 +1270,9 @@ void PrepareUnload(Vehicle *front_v)
|
||||
assert(CargoPayment::CanAllocateItem());
|
||||
front_v->cargo_payment = new CargoPayment(front_v);
|
||||
|
||||
StationIDStack next_station = front_v->GetNextStoppingStation();
|
||||
if (front_v->orders == nullptr || (front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
|
||||
std::vector<StationID> next_station;
|
||||
front_v->GetNextStoppingStation(next_station);
|
||||
if (front_v->orders == nullptr || front_v->current_order.GetUnloadType() != OrderUnloadType::NoUnload) {
|
||||
Station *st = Station::Get(front_v->last_station_visited);
|
||||
for (Vehicle *v = front_v; v != nullptr; v = v->Next()) {
|
||||
const GoodsEntry *ge = &st->goods[v->cargo_type];
|
||||
@@ -1433,7 +1434,7 @@ struct FinalizeRefitAction
|
||||
{
|
||||
CargoArray &consist_capleft; ///< Capacities left in the consist.
|
||||
Station *st; ///< Station to reserve cargo from.
|
||||
StationIDStack &next_station; ///< Next hops to reserve cargo for.
|
||||
std::span<const StationID> next_station; ///< Next hops to reserve cargo for.
|
||||
bool do_reserve; ///< If the vehicle should reserve.
|
||||
|
||||
/**
|
||||
@@ -1443,7 +1444,7 @@ struct FinalizeRefitAction
|
||||
* @param next_station Next hops to reserve cargo for.
|
||||
* @param do_reserve If we should reserve cargo or just add up the capacities.
|
||||
*/
|
||||
FinalizeRefitAction(CargoArray &consist_capleft, Station *st, StationIDStack &next_station, bool do_reserve) :
|
||||
FinalizeRefitAction(CargoArray &consist_capleft, Station *st, std::span<const StationID> next_station, bool do_reserve) :
|
||||
consist_capleft(consist_capleft), st(st), next_station(next_station), do_reserve(do_reserve) {}
|
||||
|
||||
/**
|
||||
@@ -1471,7 +1472,7 @@ struct FinalizeRefitAction
|
||||
* @param next_station Possible next stations the vehicle can travel to.
|
||||
* @param new_cargo_type Target cargo for refit.
|
||||
*/
|
||||
static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station *st, StationIDStack next_station, CargoType new_cargo_type)
|
||||
static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station *st, std::span<const StationID> next_station, CargoType new_cargo_type)
|
||||
{
|
||||
Vehicle *v_start = v->GetFirstEnginePart();
|
||||
if (!IterateVehicleParts(v_start, IsEmptyAction())) return;
|
||||
@@ -1520,7 +1521,7 @@ static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station
|
||||
|
||||
/* Add new capacity to consist capacity and reserve cargo */
|
||||
IterateVehicleParts(v_start, FinalizeRefitAction(consist_capleft, st, next_station,
|
||||
is_auto_refit || (v->First()->current_order.GetLoadType() & OLFB_FULL_LOAD) != 0));
|
||||
is_auto_refit || v->First()->current_order.IsFullLoadOrder()));
|
||||
|
||||
cur_company.Restore();
|
||||
}
|
||||
@@ -1538,16 +1539,16 @@ static bool MayLoadUnderExclusiveRights(const Station *st, const Vehicle *v)
|
||||
|
||||
struct ReserveCargoAction {
|
||||
Station *st;
|
||||
StationIDStack *next_station;
|
||||
std::span<const StationID> next_station;
|
||||
|
||||
ReserveCargoAction(Station *st, StationIDStack *next_station) :
|
||||
ReserveCargoAction(Station *st, std::span<const StationID> next_station) :
|
||||
st(st), next_station(next_station) {}
|
||||
|
||||
bool operator()(Vehicle *v)
|
||||
{
|
||||
if (v->cargo_cap > v->cargo.RemainingCount() && MayLoadUnderExclusiveRights(st, v)) {
|
||||
st->goods[v->cargo_type].GetOrCreateData().cargo.Reserve(v->cargo_cap - v->cargo.RemainingCount(),
|
||||
&v->cargo, *next_station, v->GetCargoTile());
|
||||
&v->cargo, next_station, v->GetCargoTile());
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1563,7 +1564,7 @@ struct ReserveCargoAction {
|
||||
* @param consist_capleft If given, save free capacities after reserving there.
|
||||
* @param next_station Station(s) the vehicle will stop at next.
|
||||
*/
|
||||
static void ReserveConsist(Station *st, Vehicle *u, CargoArray *consist_capleft, StationIDStack *next_station)
|
||||
static void ReserveConsist(Station *st, Vehicle *u, CargoArray *consist_capleft, std::span<const StationID> next_station)
|
||||
{
|
||||
/* If there is a cargo payment not all vehicles of the consist have tried to do the refit.
|
||||
* In that case, only reserve if it's a fixed refit and the equivalent of "articulated chain"
|
||||
@@ -1618,14 +1619,15 @@ static void LoadUnloadVehicle(Vehicle *front)
|
||||
StationID last_visited = front->last_station_visited;
|
||||
Station *st = Station::Get(last_visited);
|
||||
|
||||
StationIDStack next_station = front->GetNextStoppingStation();
|
||||
std::vector<StationID> next_station;
|
||||
front->GetNextStoppingStation(next_station);
|
||||
bool use_autorefit = front->current_order.IsRefit() && front->current_order.GetRefitCargo() == CARGO_AUTO_REFIT;
|
||||
CargoArray consist_capleft{};
|
||||
if (_settings_game.order.improved_load && use_autorefit ?
|
||||
front->cargo_payment == nullptr : (front->current_order.GetLoadType() & OLFB_FULL_LOAD) != 0) {
|
||||
front->cargo_payment == nullptr : (front->current_order.IsFullLoadOrder())) {
|
||||
ReserveConsist(st, front,
|
||||
(use_autorefit && front->load_unload_ticks != 0) ? &consist_capleft : nullptr,
|
||||
&next_station);
|
||||
next_station);
|
||||
}
|
||||
|
||||
/* We have not waited enough time till the next round of loading/unloading */
|
||||
@@ -1663,14 +1665,14 @@ static void LoadUnloadVehicle(Vehicle *front)
|
||||
|
||||
GoodsEntry *ge = &st->goods[v->cargo_type];
|
||||
|
||||
if (v->vehicle_flags.Test(VehicleFlag::CargoUnloading) && (front->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
|
||||
if (v->vehicle_flags.Test(VehicleFlag::CargoUnloading) && front->current_order.GetUnloadType() != OrderUnloadType::NoUnload) {
|
||||
uint cargo_count = v->cargo.UnloadCount();
|
||||
uint amount_unloaded = _settings_game.order.gradual_loading ? std::min(cargo_count, GetLoadAmount(v)) : cargo_count;
|
||||
bool remaining = false; // Are there cargo entities in this vehicle that can still be unloaded here?
|
||||
|
||||
if (!ge->status.Test(GoodsEntry::State::Acceptance) && v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER) > 0) {
|
||||
/* The station does not accept our goods anymore. */
|
||||
if (front->current_order.GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) {
|
||||
if (front->current_order.GetUnloadType() == OrderUnloadType::Transfer || front->current_order.GetUnloadType() == OrderUnloadType::Unload) {
|
||||
/* Transfer instead of delivering. */
|
||||
v->cargo.Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_TRANSFER>(
|
||||
v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER));
|
||||
@@ -1728,7 +1730,7 @@ static void LoadUnloadVehicle(Vehicle *front)
|
||||
}
|
||||
|
||||
/* Do not pick up goods when we have no-load set or loading is stopped. */
|
||||
if (front->current_order.GetLoadType() & OLFB_NO_LOAD || front->vehicle_flags.Test(VehicleFlag::StopLoading)) continue;
|
||||
if (front->current_order.GetLoadType() == OrderLoadType::NoLoad || front->vehicle_flags.Test(VehicleFlag::StopLoading)) continue;
|
||||
|
||||
/* This order has a refit, if this is the first vehicle part carrying cargo and the whole vehicle is empty, try refitting. */
|
||||
if (front->current_order.IsRefit() && artic_part == 1) {
|
||||
@@ -1852,7 +1854,7 @@ static void LoadUnloadVehicle(Vehicle *front)
|
||||
}
|
||||
/* We loaded less cargo than possible for all cargo types and it's not full
|
||||
* load and we're not supposed to wait any longer: stop loading. */
|
||||
if (!anything_unloaded && full_load_amount == 0 && reservation_left == 0 && !(front->current_order.GetLoadType() & OLFB_FULL_LOAD) &&
|
||||
if (!anything_unloaded && full_load_amount == 0 && reservation_left == 0 && !front->current_order.IsFullLoadOrder() &&
|
||||
front->current_order_time >= std::max(front->current_order.GetTimetabledWait() - front->lateness_counter, 0)) {
|
||||
front->vehicle_flags.Set(VehicleFlag::StopLoading);
|
||||
}
|
||||
@@ -1861,8 +1863,8 @@ static void LoadUnloadVehicle(Vehicle *front)
|
||||
} else {
|
||||
UpdateLoadUnloadTicks(front, st, 20); // We need the ticks for link refreshing.
|
||||
bool finished_loading = true;
|
||||
if (front->current_order.GetLoadType() & OLFB_FULL_LOAD) {
|
||||
if (front->current_order.GetLoadType() == OLF_FULL_LOAD_ANY) {
|
||||
if (front->current_order.IsFullLoadOrder()) {
|
||||
if (front->current_order.GetLoadType() == OrderLoadType::FullLoadAny) {
|
||||
/* if the aircraft carries passengers and is NOT full, then
|
||||
* continue loading, no matter how much mail is in */
|
||||
if ((front->type == VEH_AIRCRAFT && IsCargoInClass(front->cargo_type, CargoClass::Passengers) && front->cargo_cap > front->cargo.StoredCount()) ||
|
||||
|
||||
+1
-1
@@ -15,6 +15,6 @@
|
||||
|
||||
CommandCost CmdBuyCompany(DoCommandFlags flags, CompanyID target_company, bool hostile_takeover);
|
||||
|
||||
DEF_CMD_TRAIT(CMD_BUY_COMPANY, CmdBuyCompany, {}, CMDT_MONEY_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_BUY_COMPANY, CmdBuyCompany, {}, CommandType::MoneyManagement)
|
||||
|
||||
#endif /* ECONOMY_CMD_H */
|
||||
|
||||
+8
-9
@@ -89,7 +89,7 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, DiagDirections *override
|
||||
case MP_RAILWAY:
|
||||
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
|
||||
switch (GetRailTileType(t)) {
|
||||
case RAIL_TILE_NORMAL: case RAIL_TILE_SIGNALS:
|
||||
case RailTileType::Normal: case RailTileType::Signals:
|
||||
return GetTrackBits(t);
|
||||
default:
|
||||
return TRACK_BIT_NONE;
|
||||
@@ -580,15 +580,13 @@ void SettingsDisableElrail(int32_t new_value)
|
||||
|
||||
void UpdateDisableElrailSettingState(bool disable, bool update_vehicles)
|
||||
{
|
||||
/* pick appropriate railtype for elrail engines depending on setting */
|
||||
const RailType new_railtype = disable ? RAILTYPE_RAIL : RAILTYPE_ELECTRIC;
|
||||
|
||||
/* walk through all train engines */
|
||||
for (Engine *e : Engine::IterateType(VEH_TRAIN)) {
|
||||
RailVehicleInfo *rv_info = &e->u.rail;
|
||||
RailVehicleInfo *rv_info = &e->VehInfo<RailVehicleInfo>();
|
||||
/* update railtype of engines intended to use elrail */
|
||||
if (rv_info->intended_railtype == RAILTYPE_ELECTRIC) {
|
||||
rv_info->railtype = new_railtype;
|
||||
if (rv_info->intended_railtypes.Test(RAILTYPE_ELECTRIC)) {
|
||||
rv_info->railtypes.Set(RAILTYPE_ELECTRIC, !disable);
|
||||
rv_info->railtypes.Set(RAILTYPE_RAIL, disable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,11 +594,12 @@ void UpdateDisableElrailSettingState(bool disable, bool update_vehicles)
|
||||
* normal rail too */
|
||||
if (disable) {
|
||||
for (Train *t : Train::Iterate()) {
|
||||
if (t->railtype == RAILTYPE_ELECTRIC) {
|
||||
if (t->railtypes.Test(RAILTYPE_ELECTRIC)) {
|
||||
/* this railroad vehicle is now compatible only with elrail,
|
||||
* so add there also normal rail compatibility */
|
||||
t->compatible_railtypes.Set(RAILTYPE_RAIL);
|
||||
t->railtype = RAILTYPE_RAIL;
|
||||
t->railtypes.Reset(RAILTYPE_ELECTRIC);
|
||||
t->railtypes.Set(RAILTYPE_RAIL);
|
||||
t->flags.Set(VehicleRailFlag::AllowedOnNormalRail);
|
||||
}
|
||||
}
|
||||
|
||||
+68
-68
@@ -78,24 +78,19 @@ Engine::Engine(VehicleType type, uint16_t local_id)
|
||||
|
||||
/* Check if this base engine is within the original engine data range */
|
||||
if (local_id >= _engine_counts[type]) {
|
||||
/* 'power' defaults to zero, so we also have to default to 'wagon' */
|
||||
if (type == VEH_TRAIN) this->u.rail.railveh_type = RAILVEH_WAGON;
|
||||
/* Initialise default type-specific information. */
|
||||
switch (type) {
|
||||
case VEH_TRAIN: this->vehicle_info.emplace<RailVehicleInfo>(); break;
|
||||
case VEH_ROAD: this->vehicle_info.emplace<RoadVehicleInfo>(); break;
|
||||
case VEH_SHIP: this->vehicle_info.emplace<ShipVehicleInfo>(); break;
|
||||
case VEH_AIRCRAFT: this->vehicle_info.emplace<AircraftVehicleInfo>(); break;
|
||||
default: break;
|
||||
}
|
||||
/* Set model life to maximum to make wagons available */
|
||||
this->info.base_life = TimerGameCalendar::Year{0xFF};
|
||||
/* Set road vehicle tractive effort to the default value */
|
||||
if (type == VEH_ROAD) this->u.road.tractive_effort = 0x4C;
|
||||
/* Aircraft must have CT_INVALID as default, as there is no property */
|
||||
this->info.cargo_type = INVALID_CARGO;
|
||||
this->info.cargo_label = (type == VEH_AIRCRAFT) ? CT_INVALID : CT_PASSENGERS;
|
||||
/* Ships must have a non-zero acceleration. */
|
||||
if (type == VEH_SHIP) this->u.ship.acceleration = 1;
|
||||
/* Set visual effect to the default value */
|
||||
switch (type) {
|
||||
case VEH_TRAIN: this->u.rail.visual_effect = VE_DEFAULT; break;
|
||||
case VEH_ROAD: this->u.road.visual_effect = VE_DEFAULT; break;
|
||||
case VEH_SHIP: this->u.ship.visual_effect = VE_DEFAULT; break;
|
||||
default: break; // The aircraft, disasters and especially visual effects have no NewGRF configured visual effects
|
||||
}
|
||||
/* Set cargo aging period to the default value. */
|
||||
this->info.cargo_age_period = Ticks::CARGO_AGING_TICKS;
|
||||
/* Not a variant */
|
||||
@@ -110,33 +105,37 @@ Engine::Engine(VehicleType type, uint16_t local_id)
|
||||
switch (type) {
|
||||
default: NOT_REACHED();
|
||||
|
||||
case VEH_TRAIN:
|
||||
this->u.rail = _orig_rail_vehicle_info[local_id];
|
||||
this->original_image_index = this->u.rail.image_index;
|
||||
case VEH_TRAIN: {
|
||||
RailVehicleInfo &rvi = this->vehicle_info.emplace<RailVehicleInfo>(_orig_rail_vehicle_info[local_id]);
|
||||
this->original_image_index = rvi.image_index;
|
||||
this->info.string_id = STR_VEHICLE_NAME_TRAIN_ENGINE_RAIL_KIRBY_PAUL_TANK_STEAM + local_id;
|
||||
|
||||
/* Set the default model life of original wagons to "infinite" */
|
||||
if (this->u.rail.railveh_type == RAILVEH_WAGON) this->info.base_life = TimerGameCalendar::Year{0xFF};
|
||||
if (rvi.railveh_type == RAILVEH_WAGON) this->info.base_life = TimerGameCalendar::Year{0xFF};
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case VEH_ROAD:
|
||||
this->u.road = _orig_road_vehicle_info[local_id];
|
||||
this->original_image_index = this->u.road.image_index;
|
||||
case VEH_ROAD: {
|
||||
RoadVehicleInfo &rvi = this->vehicle_info.emplace<RoadVehicleInfo>(_orig_road_vehicle_info[local_id]);
|
||||
this->original_image_index = rvi.image_index;
|
||||
this->info.string_id = STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_REGAL_BUS + local_id;
|
||||
break;
|
||||
}
|
||||
|
||||
case VEH_SHIP:
|
||||
this->u.ship = _orig_ship_vehicle_info[local_id];
|
||||
this->original_image_index = this->u.ship.image_index;
|
||||
case VEH_SHIP: {
|
||||
ShipVehicleInfo &svi = this->vehicle_info.emplace<ShipVehicleInfo>(_orig_ship_vehicle_info[local_id]);
|
||||
this->original_image_index = svi.image_index;
|
||||
this->info.string_id = STR_VEHICLE_NAME_SHIP_MPS_OIL_TANKER + local_id;
|
||||
break;
|
||||
}
|
||||
|
||||
case VEH_AIRCRAFT:
|
||||
this->u.air = _orig_aircraft_vehicle_info[local_id];
|
||||
this->original_image_index = this->u.air.image_index;
|
||||
case VEH_AIRCRAFT: {
|
||||
AircraftVehicleInfo &avi = this->vehicle_info.emplace<AircraftVehicleInfo>(_orig_aircraft_vehicle_info[local_id]);
|
||||
this->original_image_index = avi.image_index;
|
||||
this->info.string_id = STR_VEHICLE_NAME_AIRCRAFT_SAMPSON_U52 + local_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,11 +173,11 @@ bool Engine::CanCarryCargo() const
|
||||
*/
|
||||
switch (this->type) {
|
||||
case VEH_TRAIN:
|
||||
if (this->u.rail.capacity == 0) return false;
|
||||
if (this->VehInfo<RailVehicleInfo>().capacity == 0) return false;
|
||||
break;
|
||||
|
||||
case VEH_ROAD:
|
||||
if (this->u.road.capacity == 0) return false;
|
||||
if (this->VehInfo<RoadVehicleInfo>().capacity == 0) return false;
|
||||
break;
|
||||
|
||||
case VEH_SHIP:
|
||||
@@ -210,7 +209,7 @@ uint Engine::DetermineCapacity(const Vehicle *v, uint16_t *mail_capacity) const
|
||||
CargoType cargo_type = (v != nullptr) ? v->cargo_type : default_cargo;
|
||||
|
||||
if (mail_capacity != nullptr && this->type == VEH_AIRCRAFT && IsCargoInClass(cargo_type, CargoClass::Passengers)) {
|
||||
*mail_capacity = GetEngineProperty(this->index, PROP_AIRCRAFT_MAIL_CAPACITY, this->u.air.mail_capacity, v);
|
||||
*mail_capacity = GetEngineProperty(this->index, PROP_AIRCRAFT_MAIL_CAPACITY, this->VehInfo<AircraftVehicleInfo>().mail_capacity, v);
|
||||
}
|
||||
|
||||
/* Check the refit capacity callback if we are not in the default configuration, or if we are using the new multiplier algorithm. */
|
||||
@@ -225,24 +224,24 @@ uint Engine::DetermineCapacity(const Vehicle *v, uint16_t *mail_capacity) const
|
||||
uint extra_mail_cap = 0;
|
||||
switch (this->type) {
|
||||
case VEH_TRAIN:
|
||||
capacity = GetEngineProperty(this->index, PROP_TRAIN_CARGO_CAPACITY, this->u.rail.capacity, v);
|
||||
capacity = GetEngineProperty(this->index, PROP_TRAIN_CARGO_CAPACITY, this->VehInfo<RailVehicleInfo>().capacity, v);
|
||||
|
||||
/* In purchase list add the capacity of the second head. Always use the plain property for this. */
|
||||
if (v == nullptr && this->u.rail.railveh_type == RAILVEH_MULTIHEAD) capacity += this->u.rail.capacity;
|
||||
if (v == nullptr && this->VehInfo<RailVehicleInfo>().railveh_type == RAILVEH_MULTIHEAD) capacity += this->VehInfo<RailVehicleInfo>().capacity;
|
||||
break;
|
||||
|
||||
case VEH_ROAD:
|
||||
capacity = GetEngineProperty(this->index, PROP_ROADVEH_CARGO_CAPACITY, this->u.road.capacity, v);
|
||||
capacity = GetEngineProperty(this->index, PROP_ROADVEH_CARGO_CAPACITY, this->VehInfo<RoadVehicleInfo>().capacity, v);
|
||||
break;
|
||||
|
||||
case VEH_SHIP:
|
||||
capacity = GetEngineProperty(this->index, PROP_SHIP_CARGO_CAPACITY, this->u.ship.capacity, v);
|
||||
capacity = GetEngineProperty(this->index, PROP_SHIP_CARGO_CAPACITY, this->VehInfo<ShipVehicleInfo>().capacity, v);
|
||||
break;
|
||||
|
||||
case VEH_AIRCRAFT:
|
||||
capacity = GetEngineProperty(this->index, PROP_AIRCRAFT_PASSENGER_CAPACITY, this->u.air.passenger_capacity, v);
|
||||
capacity = GetEngineProperty(this->index, PROP_AIRCRAFT_PASSENGER_CAPACITY, this->VehInfo<AircraftVehicleInfo>().passenger_capacity, v);
|
||||
if (!IsCargoInClass(cargo_type, CargoClass::Passengers)) {
|
||||
extra_mail_cap = GetEngineProperty(this->index, PROP_AIRCRAFT_MAIL_CAPACITY, this->u.air.mail_capacity, v);
|
||||
extra_mail_cap = GetEngineProperty(this->index, PROP_AIRCRAFT_MAIL_CAPACITY, this->VehInfo<AircraftVehicleInfo>().mail_capacity, v);
|
||||
}
|
||||
if (IsValidCargoType(GetCargoTypeByLabel(CT_MAIL))) {
|
||||
if (!new_multipliers && cargo_type == GetCargoTypeByLabel(CT_MAIL)) return capacity + extra_mail_cap;
|
||||
@@ -284,25 +283,25 @@ Money Engine::GetRunningCost() const
|
||||
uint cost_factor;
|
||||
switch (this->type) {
|
||||
case VEH_ROAD:
|
||||
base_price = this->u.road.running_cost_class;
|
||||
base_price = this->VehInfo<RoadVehicleInfo>().running_cost_class;
|
||||
if (base_price == INVALID_PRICE) return 0;
|
||||
cost_factor = GetEngineProperty(this->index, PROP_ROADVEH_RUNNING_COST_FACTOR, this->u.road.running_cost);
|
||||
cost_factor = GetEngineProperty(this->index, PROP_ROADVEH_RUNNING_COST_FACTOR, this->VehInfo<RoadVehicleInfo>().running_cost);
|
||||
break;
|
||||
|
||||
case VEH_TRAIN:
|
||||
base_price = this->u.rail.running_cost_class;
|
||||
base_price = this->VehInfo<RailVehicleInfo>().running_cost_class;
|
||||
if (base_price == INVALID_PRICE) return 0;
|
||||
cost_factor = GetEngineProperty(this->index, PROP_TRAIN_RUNNING_COST_FACTOR, this->u.rail.running_cost);
|
||||
cost_factor = GetEngineProperty(this->index, PROP_TRAIN_RUNNING_COST_FACTOR, this->VehInfo<RailVehicleInfo>().running_cost);
|
||||
break;
|
||||
|
||||
case VEH_SHIP:
|
||||
base_price = PR_RUNNING_SHIP;
|
||||
cost_factor = GetEngineProperty(this->index, PROP_SHIP_RUNNING_COST_FACTOR, this->u.ship.running_cost);
|
||||
cost_factor = GetEngineProperty(this->index, PROP_SHIP_RUNNING_COST_FACTOR, this->VehInfo<ShipVehicleInfo>().running_cost);
|
||||
break;
|
||||
|
||||
case VEH_AIRCRAFT:
|
||||
base_price = PR_RUNNING_AIRCRAFT;
|
||||
cost_factor = GetEngineProperty(this->index, PROP_AIRCRAFT_RUNNING_COST_FACTOR, this->u.air.running_cost);
|
||||
cost_factor = GetEngineProperty(this->index, PROP_AIRCRAFT_RUNNING_COST_FACTOR, this->VehInfo<AircraftVehicleInfo>().running_cost);
|
||||
break;
|
||||
|
||||
default: NOT_REACHED();
|
||||
@@ -322,27 +321,27 @@ Money Engine::GetCost() const
|
||||
switch (this->type) {
|
||||
case VEH_ROAD:
|
||||
base_price = PR_BUILD_VEHICLE_ROAD;
|
||||
cost_factor = GetEngineProperty(this->index, PROP_ROADVEH_COST_FACTOR, this->u.road.cost_factor);
|
||||
cost_factor = GetEngineProperty(this->index, PROP_ROADVEH_COST_FACTOR, this->VehInfo<RoadVehicleInfo>().cost_factor);
|
||||
break;
|
||||
|
||||
case VEH_TRAIN:
|
||||
if (this->u.rail.railveh_type == RAILVEH_WAGON) {
|
||||
if (this->VehInfo<RailVehicleInfo>().railveh_type == RAILVEH_WAGON) {
|
||||
base_price = PR_BUILD_VEHICLE_WAGON;
|
||||
cost_factor = GetEngineProperty(this->index, PROP_TRAIN_COST_FACTOR, this->u.rail.cost_factor);
|
||||
cost_factor = GetEngineProperty(this->index, PROP_TRAIN_COST_FACTOR, this->VehInfo<RailVehicleInfo>().cost_factor);
|
||||
} else {
|
||||
base_price = PR_BUILD_VEHICLE_TRAIN;
|
||||
cost_factor = GetEngineProperty(this->index, PROP_TRAIN_COST_FACTOR, this->u.rail.cost_factor);
|
||||
cost_factor = GetEngineProperty(this->index, PROP_TRAIN_COST_FACTOR, this->VehInfo<RailVehicleInfo>().cost_factor);
|
||||
}
|
||||
break;
|
||||
|
||||
case VEH_SHIP:
|
||||
base_price = PR_BUILD_VEHICLE_SHIP;
|
||||
cost_factor = GetEngineProperty(this->index, PROP_SHIP_COST_FACTOR, this->u.ship.cost_factor);
|
||||
cost_factor = GetEngineProperty(this->index, PROP_SHIP_COST_FACTOR, this->VehInfo<ShipVehicleInfo>().cost_factor);
|
||||
break;
|
||||
|
||||
case VEH_AIRCRAFT:
|
||||
base_price = PR_BUILD_VEHICLE_AIRCRAFT;
|
||||
cost_factor = GetEngineProperty(this->index, PROP_AIRCRAFT_COST_FACTOR, this->u.air.cost_factor);
|
||||
cost_factor = GetEngineProperty(this->index, PROP_AIRCRAFT_COST_FACTOR, this->VehInfo<AircraftVehicleInfo>().cost_factor);
|
||||
break;
|
||||
|
||||
default: NOT_REACHED();
|
||||
@@ -359,22 +358,22 @@ uint Engine::GetDisplayMaxSpeed() const
|
||||
{
|
||||
switch (this->type) {
|
||||
case VEH_TRAIN:
|
||||
return GetEngineProperty(this->index, PROP_TRAIN_SPEED, this->u.rail.max_speed);
|
||||
return GetEngineProperty(this->index, PROP_TRAIN_SPEED, this->VehInfo<RailVehicleInfo>().max_speed);
|
||||
|
||||
case VEH_ROAD: {
|
||||
uint max_speed = GetEngineProperty(this->index, PROP_ROADVEH_SPEED, 0);
|
||||
return (max_speed != 0) ? max_speed * 2 : this->u.road.max_speed / 2;
|
||||
return (max_speed != 0) ? max_speed * 2 : this->VehInfo<RoadVehicleInfo>().max_speed / 2;
|
||||
}
|
||||
|
||||
case VEH_SHIP:
|
||||
return GetEngineProperty(this->index, PROP_SHIP_SPEED, this->u.ship.max_speed) / 2;
|
||||
return GetEngineProperty(this->index, PROP_SHIP_SPEED, this->VehInfo<ShipVehicleInfo>().max_speed) / 2;
|
||||
|
||||
case VEH_AIRCRAFT: {
|
||||
uint max_speed = GetEngineProperty(this->index, PROP_AIRCRAFT_SPEED, 0);
|
||||
if (max_speed != 0) {
|
||||
return (max_speed * 128) / 10;
|
||||
}
|
||||
return this->u.air.max_speed;
|
||||
return this->VehInfo<AircraftVehicleInfo>().max_speed;
|
||||
}
|
||||
|
||||
default: NOT_REACHED();
|
||||
@@ -392,9 +391,9 @@ uint Engine::GetPower() const
|
||||
/* Only trains and road vehicles have 'power'. */
|
||||
switch (this->type) {
|
||||
case VEH_TRAIN:
|
||||
return GetEngineProperty(this->index, PROP_TRAIN_POWER, this->u.rail.power);
|
||||
return GetEngineProperty(this->index, PROP_TRAIN_POWER, this->VehInfo<RailVehicleInfo>().power);
|
||||
case VEH_ROAD:
|
||||
return GetEngineProperty(this->index, PROP_ROADVEH_POWER, this->u.road.power) * 10;
|
||||
return GetEngineProperty(this->index, PROP_ROADVEH_POWER, this->VehInfo<RoadVehicleInfo>().power) * 10;
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
@@ -410,9 +409,9 @@ uint Engine::GetDisplayWeight() const
|
||||
/* Only trains and road vehicles have 'weight'. */
|
||||
switch (this->type) {
|
||||
case VEH_TRAIN:
|
||||
return GetEngineProperty(this->index, PROP_TRAIN_WEIGHT, this->u.rail.weight) << (this->u.rail.railveh_type == RAILVEH_MULTIHEAD ? 1 : 0);
|
||||
return GetEngineProperty(this->index, PROP_TRAIN_WEIGHT, this->VehInfo<RailVehicleInfo>().weight) << (this->VehInfo<RailVehicleInfo>().railveh_type == RAILVEH_MULTIHEAD ? 1 : 0);
|
||||
case VEH_ROAD:
|
||||
return GetEngineProperty(this->index, PROP_ROADVEH_WEIGHT, this->u.road.weight) / 4;
|
||||
return GetEngineProperty(this->index, PROP_ROADVEH_WEIGHT, this->VehInfo<RoadVehicleInfo>().weight) / 4;
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
@@ -428,9 +427,9 @@ uint Engine::GetDisplayMaxTractiveEffort() const
|
||||
/* Only trains and road vehicles have 'tractive effort'. */
|
||||
switch (this->type) {
|
||||
case VEH_TRAIN:
|
||||
return (GROUND_ACCELERATION * this->GetDisplayWeight() * GetEngineProperty(this->index, PROP_TRAIN_TRACTIVE_EFFORT, this->u.rail.tractive_effort)) / 256;
|
||||
return (GROUND_ACCELERATION * this->GetDisplayWeight() * GetEngineProperty(this->index, PROP_TRAIN_TRACTIVE_EFFORT, this->VehInfo<RailVehicleInfo>().tractive_effort)) / 256;
|
||||
case VEH_ROAD:
|
||||
return (GROUND_ACCELERATION * this->GetDisplayWeight() * GetEngineProperty(this->index, PROP_ROADVEH_TRACTIVE_EFFORT, this->u.road.tractive_effort)) / 256;
|
||||
return (GROUND_ACCELERATION * this->GetDisplayWeight() * GetEngineProperty(this->index, PROP_ROADVEH_TRACTIVE_EFFORT, this->VehInfo<RoadVehicleInfo>().tractive_effort)) / 256;
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
@@ -454,7 +453,7 @@ uint16_t Engine::GetRange() const
|
||||
{
|
||||
switch (this->type) {
|
||||
case VEH_AIRCRAFT:
|
||||
return GetEngineProperty(this->index, PROP_AIRCRAFT_RANGE, this->u.air.max_range);
|
||||
return GetEngineProperty(this->index, PROP_AIRCRAFT_RANGE, this->VehInfo<AircraftVehicleInfo>().max_range);
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
@@ -468,7 +467,7 @@ StringID Engine::GetAircraftTypeText() const
|
||||
{
|
||||
switch (this->type) {
|
||||
case VEH_AIRCRAFT:
|
||||
switch (this->u.air.subtype) {
|
||||
switch (this->VehInfo<AircraftVehicleInfo>().subtype) {
|
||||
case AIR_HELI: return STR_LIVERY_HELICOPTER;
|
||||
case AIR_CTOL: return STR_LIVERY_SMALL_PLANE;
|
||||
case AIR_CTOL | AIR_FAST: return STR_LIVERY_LARGE_PLANE;
|
||||
@@ -625,7 +624,7 @@ void ShowEnginePreviewWindow(EngineID engine);
|
||||
static bool IsWagon(EngineID index)
|
||||
{
|
||||
const Engine *e = Engine::Get(index);
|
||||
return e->type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON;
|
||||
return e->type == VEH_TRAIN && e->VehInfo<RailVehicleInfo>().railveh_type == RAILVEH_WAGON;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -700,7 +699,7 @@ void SetYearEngineAgingStops()
|
||||
|
||||
/* Exclude certain engines */
|
||||
if (!ei->climates.Test(_settings_game.game_creation.landscape)) continue;
|
||||
if (e->type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON) continue;
|
||||
if (e->type == VEH_TRAIN && e->VehInfo<RailVehicleInfo>().railveh_type == RAILVEH_WAGON) continue;
|
||||
|
||||
/* Base year ending date on half the model life */
|
||||
TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(ei->base_intro + (ei->lifelength.base() * CalendarTime::DAYS_IN_LEAP_YEAR) / 2);
|
||||
@@ -1107,12 +1106,13 @@ static void NewVehicleAvailable(Engine *e)
|
||||
|
||||
if (e->type == VEH_TRAIN) {
|
||||
/* maybe make another rail type available */
|
||||
assert(e->u.rail.railtype < RAILTYPE_END);
|
||||
for (Company *c : Company::Iterate()) c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes | GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes, TimerGameCalendar::date);
|
||||
assert(e->VehInfo<RailVehicleInfo>().railtypes != RailTypes{});
|
||||
RailTypes introduced = GetAllIntroducesRailTypes(e->VehInfo<RailVehicleInfo>().railtypes);
|
||||
for (Company *c : Company::Iterate()) c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes | introduced, TimerGameCalendar::date);
|
||||
} else if (e->type == VEH_ROAD) {
|
||||
/* maybe make another road type available */
|
||||
assert(e->u.road.roadtype < ROADTYPE_END);
|
||||
for (Company *c : Company::Iterate()) c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes | GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes, TimerGameCalendar::date);
|
||||
assert(e->VehInfo<RoadVehicleInfo>().roadtype < ROADTYPE_END);
|
||||
for (Company *c : Company::Iterate()) c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes | GetRoadTypeInfo(e->VehInfo<RoadVehicleInfo>().roadtype)->introduces_roadtypes, TimerGameCalendar::date);
|
||||
}
|
||||
|
||||
/* Only broadcast event if AIs are able to build this vehicle type. */
|
||||
@@ -1267,12 +1267,12 @@ bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company)
|
||||
if (type == VEH_TRAIN && company != OWNER_DEITY) {
|
||||
/* Check if the rail type is available to this company */
|
||||
const Company *c = Company::Get(company);
|
||||
if (!GetRailTypeInfo(e->u.rail.railtype)->compatible_railtypes.Any(c->avail_railtypes)) return false;
|
||||
if (!GetAllCompatibleRailTypes(e->VehInfo<RailVehicleInfo>().railtypes).Any(c->avail_railtypes)) return false;
|
||||
}
|
||||
if (type == VEH_ROAD && company != OWNER_DEITY) {
|
||||
/* Check if the road type is available to this company */
|
||||
const Company *c = Company::Get(company);
|
||||
if (!GetRoadTypeInfo(e->u.road.roadtype)->powered_roadtypes.Any(c->avail_roadtypes)) return false;
|
||||
if (!GetRoadTypeInfo(e->VehInfo<RoadVehicleInfo>().roadtype)->powered_roadtypes.Any(c->avail_roadtypes)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1318,7 +1318,7 @@ void CheckEngines()
|
||||
if (!e->IsEnabled()) continue;
|
||||
|
||||
/* Don't consider train wagons, we need a powered engine available. */
|
||||
if (e->type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON) continue;
|
||||
if (e->type == VEH_TRAIN && e->VehInfo<RailVehicleInfo>().railveh_type == RAILVEH_WAGON) continue;
|
||||
|
||||
/* We have an available engine... yay! */
|
||||
if (e->flags.Test(EngineFlag::Available) && e->company_avail.Any()) return;
|
||||
|
||||
+23
-12
@@ -35,7 +35,8 @@ using EngineDisplayFlags = EnumBitSet<EngineDisplayFlag, uint8_t>;
|
||||
typedef Pool<Engine, EngineID, 64> EnginePool;
|
||||
extern EnginePool _engine_pool;
|
||||
|
||||
struct Engine : EnginePool::PoolItem<&_engine_pool> {
|
||||
class Engine : public EnginePool::PoolItem<&_engine_pool> {
|
||||
public:
|
||||
CompanyMask company_avail{}; ///< Bit for each company whether the engine is available for that company.
|
||||
CompanyMask company_hidden{}; ///< Bit for each company whether the engine is normally hidden in the build gui for that company.
|
||||
CompanyMask preview_asked{}; ///< Bit for each company which has already been offered a preview.
|
||||
@@ -64,13 +65,6 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> {
|
||||
EngineID display_last_variant = EngineID::Invalid(); ///< NOSAVE client-side-only last variant selected.
|
||||
EngineInfo info{};
|
||||
|
||||
union {
|
||||
RailVehicleInfo rail;
|
||||
RoadVehicleInfo road;
|
||||
ShipVehicleInfo ship;
|
||||
AircraftVehicleInfo air;
|
||||
} u{};
|
||||
|
||||
uint16_t list_position = 0;
|
||||
|
||||
/* NewGRF related data */
|
||||
@@ -78,6 +72,11 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> {
|
||||
std::vector<WagonOverride> overrides{};
|
||||
std::vector<BadgeID> badges{};
|
||||
|
||||
private:
|
||||
/* Vehicle-type specific information. */
|
||||
std::variant<std::monostate, RailVehicleInfo, RoadVehicleInfo, ShipVehicleInfo, AircraftVehicleInfo> vehicle_info{};
|
||||
|
||||
public:
|
||||
Engine() {}
|
||||
Engine(VehicleType type, uint16_t local_id);
|
||||
bool IsEnabled() const;
|
||||
@@ -177,6 +176,18 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> {
|
||||
bool operator() (size_t index) { return Engine::Get(index)->type == this->vt; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline T &VehInfo()
|
||||
{
|
||||
return std::get<T>(this->vehicle_info);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline const T &VehInfo() const
|
||||
{
|
||||
return std::get<T>(this->vehicle_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterable ensemble of all valid engines of the given type
|
||||
* @param vt the VehicleType for engines to be valid
|
||||
@@ -234,22 +245,22 @@ inline const EngineInfo *EngInfo(EngineID e)
|
||||
|
||||
inline const RailVehicleInfo *RailVehInfo(EngineID e)
|
||||
{
|
||||
return &Engine::Get(e)->u.rail;
|
||||
return &Engine::Get(e)->VehInfo<RailVehicleInfo>();
|
||||
}
|
||||
|
||||
inline const RoadVehicleInfo *RoadVehInfo(EngineID e)
|
||||
{
|
||||
return &Engine::Get(e)->u.road;
|
||||
return &Engine::Get(e)->VehInfo<RoadVehicleInfo>();
|
||||
}
|
||||
|
||||
inline const ShipVehicleInfo *ShipVehInfo(EngineID e)
|
||||
{
|
||||
return &Engine::Get(e)->u.ship;
|
||||
return &Engine::Get(e)->VehInfo<ShipVehicleInfo>();
|
||||
}
|
||||
|
||||
inline const AircraftVehicleInfo *AircraftVehInfo(EngineID e)
|
||||
{
|
||||
return &Engine::Get(e)->u.air;
|
||||
return &Engine::Get(e)->VehInfo<AircraftVehicleInfo>();
|
||||
}
|
||||
|
||||
#endif /* ENGINE_BASE_H */
|
||||
|
||||
+4
-4
@@ -17,9 +17,9 @@ CommandCost CmdEngineCtrl(DoCommandFlags flags, EngineID engine_id, CompanyID co
|
||||
CommandCost CmdRenameEngine(DoCommandFlags flags, EngineID engine_id, const std::string &text);
|
||||
CommandCost CmdSetVehicleVisibility(DoCommandFlags flags, EngineID engine_id, bool hide);
|
||||
|
||||
DEF_CMD_TRAIT(CMD_WANT_ENGINE_PREVIEW, CmdWantEnginePreview, {}, CMDT_VEHICLE_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_ENGINE_CTRL, CmdEngineCtrl, CommandFlag::Deity, CMDT_VEHICLE_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_RENAME_ENGINE, CmdRenameEngine, CommandFlag::Server, CMDT_OTHER_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_SET_VEHICLE_VISIBILITY, CmdSetVehicleVisibility, {}, CMDT_COMPANY_SETTING)
|
||||
DEF_CMD_TRAIT(CMD_WANT_ENGINE_PREVIEW, CmdWantEnginePreview, {}, CommandType::VehicleManagement)
|
||||
DEF_CMD_TRAIT(CMD_ENGINE_CTRL, CmdEngineCtrl, CommandFlag::Deity, CommandType::VehicleManagement)
|
||||
DEF_CMD_TRAIT(CMD_RENAME_ENGINE, CmdRenameEngine, CommandFlag::Server, CommandType::OtherManagement)
|
||||
DEF_CMD_TRAIT(CMD_SET_VEHICLE_VISIBILITY, CmdSetVehicleVisibility, {}, CommandType::CompanySetting)
|
||||
|
||||
#endif /* ENGINE_CMD_H */
|
||||
|
||||
+24
-4
@@ -43,15 +43,16 @@ StringID GetEngineCategoryName(EngineID engine)
|
||||
switch (e->type) {
|
||||
default: NOT_REACHED();
|
||||
case VEH_ROAD:
|
||||
return GetRoadTypeInfo(e->u.road.roadtype)->strings.new_engine;
|
||||
return GetRoadTypeInfo(e->VehInfo<RoadVehicleInfo>().roadtype)->strings.new_engine;
|
||||
case VEH_AIRCRAFT: return STR_ENGINE_PREVIEW_AIRCRAFT;
|
||||
case VEH_SHIP: return STR_ENGINE_PREVIEW_SHIP;
|
||||
case VEH_TRAIN:
|
||||
return GetRailTypeInfo(e->u.rail.railtype)->strings.new_loco;
|
||||
assert(e->VehInfo<RailVehicleInfo>().railtypes.Any());
|
||||
return GetRailTypeInfo(e->VehInfo<RailVehicleInfo>().railtypes.GetNthSetBit(0).value())->strings.new_loco;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr NWidgetPart _nested_engine_preview_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_engine_preview_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
|
||||
NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetStringTip(STR_ENGINE_PREVIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
@@ -181,7 +182,26 @@ static std::string GetTrainEngineInfoString(const Engine &e)
|
||||
res << GetString(STR_ENGINE_PREVIEW_COST_WEIGHT, e.GetCost(), e.GetDisplayWeight());
|
||||
res << '\n';
|
||||
|
||||
if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL && GetRailTypeInfo(e.u.rail.railtype)->acceleration_type != 2) {
|
||||
if (e.VehInfo<RailVehicleInfo>().railtypes.Count() > 1) {
|
||||
std::string railtypes{};
|
||||
std::string_view list_separator = GetListSeparator();
|
||||
|
||||
for (const auto &rt : _sorted_railtypes) {
|
||||
if (!e.VehInfo<RailVehicleInfo>().railtypes.Test(rt)) continue;
|
||||
|
||||
if (!railtypes.empty()) railtypes += list_separator;
|
||||
AppendStringInPlace(railtypes, GetRailTypeInfo(rt)->strings.name);
|
||||
}
|
||||
res << GetString(STR_ENGINE_PREVIEW_RAILTYPES, railtypes);
|
||||
res << '\n';
|
||||
}
|
||||
|
||||
bool is_maglev = true;
|
||||
for (RailType rt : e.VehInfo<RailVehicleInfo>().railtypes) {
|
||||
is_maglev &= GetRailTypeInfo(rt)->acceleration_type == VehicleAccelerationModel::Maglev;
|
||||
}
|
||||
|
||||
if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL && !is_maglev) {
|
||||
res << GetString(STR_ENGINE_PREVIEW_SPEED_POWER_MAX_TE, PackVelocity(e.GetDisplayMaxSpeed(), e.type), e.GetPower(), e.GetDisplayMaxTractiveEffort());
|
||||
res << '\n';
|
||||
} else {
|
||||
|
||||
+36
-9
@@ -25,7 +25,7 @@
|
||||
/** Unique identification number of an engine. */
|
||||
using EngineID = PoolID<uint16_t, struct EngineIDTag, 64000, 0xFFFF>;
|
||||
|
||||
struct Engine;
|
||||
class Engine;
|
||||
|
||||
/** Available types of rail vehicles. */
|
||||
enum RailVehicleTypes : uint8_t {
|
||||
@@ -43,13 +43,40 @@ enum EngineClass : uint8_t {
|
||||
EC_MAGLEV, ///< Maglev engine.
|
||||
};
|
||||
|
||||
/** Acceleration model of a vehicle. */
|
||||
enum class VehicleAccelerationModel : uint8_t {
|
||||
Normal, ///< Default acceleration model.
|
||||
Monorail, ///< Monorail acceleration model.
|
||||
Maglev, ///< Maglev acceleration model.
|
||||
};
|
||||
|
||||
/** Meaning of the various bits of the visual effect. */
|
||||
enum VisualEffect : uint8_t {
|
||||
VE_OFFSET_START = 0, ///< First bit that contains the offset (0 = front, 8 = centre, 15 = rear)
|
||||
VE_OFFSET_COUNT = 4, ///< Number of bits used for the offset
|
||||
VE_OFFSET_CENTRE = 8, ///< Value of offset corresponding to a position above the centre of the vehicle
|
||||
|
||||
VE_TYPE_START = 4, ///< First bit used for the type of effect
|
||||
VE_TYPE_COUNT = 2, ///< Number of bits used for the effect type
|
||||
VE_TYPE_DEFAULT = 0, ///< Use default from engine class
|
||||
VE_TYPE_STEAM = 1, ///< Steam plumes
|
||||
VE_TYPE_DIESEL = 2, ///< Diesel fumes
|
||||
VE_TYPE_ELECTRIC = 3, ///< Electric sparks
|
||||
|
||||
VE_DISABLE_EFFECT = 6, ///< Flag to disable visual effect
|
||||
VE_ADVANCED_EFFECT = VE_DISABLE_EFFECT, ///< Flag for advanced effects
|
||||
VE_DISABLE_WAGON_POWER = 7, ///< Flag to disable wagon power
|
||||
|
||||
VE_DEFAULT = 0xFF, ///< Default value to indicate that visual effect should be based on engine class
|
||||
};
|
||||
|
||||
/** Information about a rail vehicle. */
|
||||
struct RailVehicleInfo {
|
||||
uint8_t image_index = 0;
|
||||
RailVehicleTypes railveh_type{};
|
||||
RailVehicleTypes railveh_type = RAILVEH_WAGON;
|
||||
uint8_t cost_factor = 0; ///< Purchase cost factor; For multiheaded engines the sum of both engine prices.
|
||||
RailType railtype{}; ///< Railtype, mangled if elrail is disabled.
|
||||
RailType intended_railtype{}; ///< Intended railtype, regardless of elrail being enabled or disabled.
|
||||
RailTypes railtypes{RAILTYPE_RAIL}; ///< Railtypes, mangled if elrail is disabled.
|
||||
RailTypes intended_railtypes{RAILTYPE_RAIL}; ///< Intended railtypes, regardless of elrail being enabled or disabled.
|
||||
uint8_t ai_passenger_only = 0; ///< Bit value to tell AI that this engine is for passenger use only
|
||||
uint16_t max_speed = 0; ///< Maximum speed (1 unit = 1/1.6 mph = 1 km-ish/h)
|
||||
uint16_t power = 0; ///< Power of engine (hp); For multiheaded engines the sum of both engine powers.
|
||||
@@ -60,7 +87,7 @@ struct RailVehicleInfo {
|
||||
uint8_t capacity = 0; ///< Cargo capacity of vehicle; For multiheaded engines the capacity of each single engine.
|
||||
uint16_t pow_wag_power = 0; ///< Extra power applied to consist if wagon should be powered
|
||||
uint8_t pow_wag_weight = 0; ///< Extra weight applied to consist if wagon should be powered
|
||||
uint8_t visual_effect = 0; ///< Bitstuffed NewGRF visual effect data
|
||||
uint8_t visual_effect = VE_DEFAULT; ///< Bitstuffed NewGRF visual effect data
|
||||
uint8_t shorten_factor = 0; ///< length on main map for this type is 8 - shorten_factor
|
||||
uint8_t tractive_effort = 0; ///< Tractive effort coefficient
|
||||
uint8_t air_drag = 0; ///< Coefficient of air drag
|
||||
@@ -73,12 +100,12 @@ struct ShipVehicleInfo {
|
||||
uint8_t image_index = 0;
|
||||
uint8_t cost_factor = 0;
|
||||
uint8_t running_cost = 0;
|
||||
uint8_t acceleration = 0; ///< Acceleration (1 unit = 1/3.2 mph per tick = 0.5 km-ish/h per tick)
|
||||
uint8_t acceleration = 1; ///< Acceleration (1 unit = 1/3.2 mph per tick = 0.5 km-ish/h per tick)
|
||||
uint16_t max_speed = 0; ///< Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h)
|
||||
uint16_t capacity = 0;
|
||||
SoundID sfx{};
|
||||
bool old_refittable = 0; ///< Is ship refittable; only used during initialisation. Later use EngineInfo::refit_mask.
|
||||
uint8_t visual_effect = 0; ///< Bitstuffed NewGRF visual effect data
|
||||
uint8_t visual_effect = VE_DEFAULT; ///< Bitstuffed NewGRF visual effect data
|
||||
uint8_t ocean_speed_frac = 0; ///< Fraction of maximum speed for ocean tiles.
|
||||
uint8_t canal_speed_frac = 0; ///< Fraction of maximum speed for canal/river tiles.
|
||||
|
||||
@@ -126,9 +153,9 @@ struct RoadVehicleInfo {
|
||||
uint8_t capacity = 0;
|
||||
uint8_t weight = 0; ///< Weight in 1/4t units
|
||||
uint8_t power = 0; ///< Power in 10hp units
|
||||
uint8_t tractive_effort = 0; ///< Coefficient of tractive effort
|
||||
uint8_t tractive_effort = 0x4C; ///< Coefficient of tractive effort
|
||||
uint8_t air_drag = 0; ///< Coefficient of air drag
|
||||
uint8_t visual_effect = 0; ///< Bitstuffed NewGRF visual effect data
|
||||
uint8_t visual_effect = VE_DEFAULT; ///< Bitstuffed NewGRF visual effect data
|
||||
uint8_t shorten_factor = 0; ///< length on main map for this type is 8 - shorten_factor
|
||||
RoadType roadtype{}; ///< Road type
|
||||
};
|
||||
|
||||
+3
-3
@@ -33,7 +33,7 @@
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
static constexpr NWidgetPart _nested_errmsg_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_errmsg_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_RED),
|
||||
NWidget(WWT_CAPTION, COLOUR_RED, WID_EM_CAPTION), SetStringTip(STR_ERROR_MESSAGE_CAPTION),
|
||||
@@ -50,7 +50,7 @@ static WindowDesc _errmsg_desc(
|
||||
_nested_errmsg_widgets
|
||||
);
|
||||
|
||||
static constexpr NWidgetPart _nested_errmsg_face_widgets[] = {
|
||||
static constexpr std::initializer_list<NWidgetPart> _nested_errmsg_face_widgets = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_RED),
|
||||
NWidget(WWT_CAPTION, COLOUR_RED, WID_EM_CAPTION),
|
||||
@@ -209,7 +209,7 @@ public:
|
||||
/* Note: NewGRF supplied error message often do not start with a colour code, so default to white. */
|
||||
Rect top_section = r.WithHeight(this->height_summary + extra, false);
|
||||
Rect bottom_section = r.WithHeight(this->height_extra + extra, true);
|
||||
Rect middle_section = { top_section.left, top_section.bottom, top_section.right, bottom_section.top };
|
||||
Rect middle_section = top_section.WithY(top_section.bottom, bottom_section.top);
|
||||
DrawStringMultiLineWithClipping(top_section, this->summary_msg.GetDecodedString(), TC_WHITE, SA_CENTER);
|
||||
DrawStringMultiLineWithClipping(middle_section, this->detailed_msg.GetDecodedString(), TC_WHITE, SA_CENTER);
|
||||
DrawStringMultiLineWithClipping(bottom_section, this->extra_msg.GetDecodedString(), TC_WHITE, SA_CENTER);
|
||||
|
||||
+7
-4
@@ -328,9 +328,12 @@ bool FioRemove(const std::string &filename)
|
||||
{
|
||||
std::filesystem::path path = OTTD2FS(filename);
|
||||
std::error_code error_code;
|
||||
std::filesystem::remove(path, error_code);
|
||||
if (error_code) {
|
||||
Debug(misc, 0, "Removing {} failed: {}", filename, error_code.message());
|
||||
if (!std::filesystem::remove(path, error_code)) {
|
||||
if (error_code) {
|
||||
Debug(misc, 0, "Removing {} failed: {}", filename, error_code.message());
|
||||
} else {
|
||||
Debug(misc, 0, "Removing {} failed: file does not exist", filename);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -590,7 +593,7 @@ bool ExtractTar(const std::string &tar_filename, Subdirectory subdir)
|
||||
/* We don't know the file. */
|
||||
if (it == _tar_list[subdir].end()) return false;
|
||||
|
||||
const auto &dirname = (*it).second;
|
||||
const auto &dirname = it->second;
|
||||
|
||||
/* The file doesn't have a sub directory! */
|
||||
if (dirname.empty()) {
|
||||
|
||||
+1
-11
@@ -230,16 +230,6 @@ std::string FiosMakeHeightmapName(std::string_view name)
|
||||
return FiosMakeFilename(_fios_path, name, fmt::format(".{}", GetCurrentScreenshotExtension()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file.
|
||||
* @param name Filename to delete.
|
||||
* @return Whether the file deletion was successful.
|
||||
*/
|
||||
bool FiosDelete(std::string_view name)
|
||||
{
|
||||
return FioRemove(FiosMakeSavegameName(name));
|
||||
}
|
||||
|
||||
typedef std::tuple<FiosType, std::string> FiosGetTypeAndNameProc(SaveLoadOperation fop, std::string_view filename, std::string_view ext);
|
||||
|
||||
/**
|
||||
@@ -517,7 +507,7 @@ std::tuple<FiosType, std::string> FiosGetHeightmapListCallback(SaveLoadOperation
|
||||
for (Searchpath sp : _valid_searchpaths) {
|
||||
std::string buf = FioGetDirectory(sp, HEIGHTMAP_DIR);
|
||||
|
||||
if (buf.compare(0, buf.size(), it->second.tar_filename, 0, buf.size()) == 0) {
|
||||
if (it->second.tar_filename.starts_with(buf)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user