From a15e584e409a769ff6907ff3c79924908c97f922 Mon Sep 17 00:00:00 2001 From: translators Date: Sat, 25 Mar 2023 18:41:51 +0000 Subject: [PATCH 01/13] Update: Translations from eints japanese: 27 changes by fmang chinese (simplified): 12 changes by XiaoJi-Game --- src/lang/japanese.txt | 51 +++++++++++++++++---------------- src/lang/simplified_chinese.txt | 12 ++++++++ 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt index f7fe18bb47..c6bdc7d5d5 100644 --- a/src/lang/japanese.txt +++ b/src/lang/japanese.txt @@ -386,9 +386,9 @@ STR_SCENEDIT_TOOLBAR_TOWN_GENERATION :{BLACK}街を STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION :{BLACK}産業を生成します STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION :{BLACK}道路を敷設します STR_SCENEDIT_TOOLBAR_TRAM_CONSTRUCTION :{BLACK}軌道敷設 -STR_SCENEDIT_TOOLBAR_PLANT_TREES :{BLACK}木を植えます。Shiftキーを押しながら決定すると費用を見積もります +STR_SCENEDIT_TOOLBAR_PLANT_TREES :{BLACK}木を植えます。Ctrlで斜めに選択できます。Shiftキーを押しながら決定すると費用を見積もります STR_SCENEDIT_TOOLBAR_PLACE_SIGN :{BLACK}標識を設置します -STR_SCENEDIT_TOOLBAR_PLACE_OBJECT :{BLACK}オブジェクトを設置します。Shiftを押しながら決定すると費用を見積もります +STR_SCENEDIT_TOOLBAR_PLACE_OBJECT :{BLACK}オブジェクトを設置します。Ctrlで斜めに選択できます。Shiftを押しながら決定すると費用を見積もります # Scenario editor file menu ###length 7 @@ -1622,7 +1622,7 @@ STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE :ダイヤに発 STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE_HELPTEXT :時刻表に出発・到着の予定時刻を表示します STR_CONFIG_SETTING_QUICKGOTO :指令の作成を高速化: {STRING} -STR_CONFIG_SETTING_QUICKGOTO_HELPTEXT :司令作成画面を開いたときに規定で「駅を選択」を選択するようにします +STR_CONFIG_SETTING_QUICKGOTO_HELPTEXT :指令作成画面を開いたときに規定で「駅を選択」を選択するようにします STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE :デフォルトの線路種類: {STRING} STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_HELPTEXT :新規ゲーム/ゲームロード直後に選択される線路の種類を指定します。「最初」では最初に開発された種類(普通は非電化の線路)、「最新」では最も新しく開発された種類、「最多」はマップ内で一番使われている種類になります @@ -1928,11 +1928,11 @@ STR_CONFIG_SETTING_LINKGRAPH_TIME :分配グラフ STR_CONFIG_SETTING_LINKGRAPH_TIME_HELPTEXT :グラフの単一要素に関わる再計算にかけられる時間を設定します。再計算が開始されると、この日数のみ実行可能なスレッドが生成されます。この設定が短いと、期日までにスレッドが終了していない可能性が高くなり、終了するまでゲームが停止します(ラグ)。長くした場合、経路が変更された場合に分配が更新されるまでに時間がかかるようになります STR_CONFIG_SETTING_DISTRIBUTION_PAX :旅客の行先分配法: {STRING} -STR_CONFIG_SETTING_DISTRIBUTION_PAX_HELPTEXT :旅客がどのように行き先別に分配されるかを設定します。「対称」ではAからBへ向かう乗客とほぼ同数が、BからAに向かうようになります。 「非対称」ではそれぞれの方向に向かう旅客数は独立に決められます。「無効」では行き先別分配をしなくなります +STR_CONFIG_SETTING_DISTRIBUTION_PAX_HELPTEXT :旅客がどのように行き先別に分配されるかを設定します。「対称」ではAからBへ向かう乗客とほぼ同数が、BからAに向かうようになります。 「非対称」ではそれぞれの方向に向かう旅客数は独立に決められます。「無効」では行き先別分配をしなくなります。 STR_CONFIG_SETTING_DISTRIBUTION_MAIL :郵便物の行先分配法: {STRING} -STR_CONFIG_SETTING_DISTRIBUTION_MAIL_HELPTEXT :郵便がどのように行き先別に分配されるかを設定します。「対称」ではAからBへ向かう郵便とほぼ同数が、BからAに向かうようになります。 「非対称」ではそれぞれの方向に向かう郵便数は独立に決められます。「無効」では行き先別分配をしなくなります +STR_CONFIG_SETTING_DISTRIBUTION_MAIL_HELPTEXT :郵便がどのように行き先別に分配されるかを設定します。「対称」ではAからBへ向かう郵便とほぼ同数が、BからAに向かうようになります。 「非対称」ではそれぞれの方向に向かう郵便数は独立に決められます。「無効」では行き先別分配をしなくなります。 STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED :装甲車輸送品の行先分配法: {STRING} -STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :装甲車輸送品とは貴重品(温帯)、金(亜寒帯)、ダイヤモンド(亜熱帯)のことです(NewGRFの導入状況よっては変わることがあります)。これらの品目ががどのように行き先別に分配されるかを設定します。「対称」ではAからBへ向かう輸送品とほぼ同数が、BからAに向かうようになります。 「非対称」ではそれぞれの方向に向かう輸送品数は独立に決められます。「手動」では自動での行き先別分配をしなくなります。亜熱帯・温帯では銀行同士で貴重品のやりとりがあるので「対称」を選択しても問題ありませんが、金やダイヤモンドが銀行から鉱山に送られるようなことはないので、亜寒帯では「非対称」か「手動」にすることをお勧めします。 +STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :装甲車輸送品とは貴重品(温帯)、金(亜寒帯)、ダイヤモンド(亜熱帯)のことです。NewGRFの導入状況よっては変わることがあります。これらの品目がどのように行き先別に分配されるかを設定します。「対称」ではAからBへ向かう輸送品とほぼ同数が、BからAに向かうようになります。 「非対称」ではそれぞれの方向に向かう輸送品数は独立に決められます。「手動」では自動での行き先別分配をしなくなります。温帯では銀行同士で貴重品のやりとりがあるので「対称」を選択しても問題ありませんが、金やダイヤモンドが銀行から鉱山に送られるようなことはないので、亜寒帯・亜熱帯では「非対称」か「手動」にすることをお勧めします。 STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT :一般貨物の行先分配法: {STRING} STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT :一般的な貨物がどのように行き先別に分配されるかを設定します。「非対称」ではそれぞれの方向に向かう貨物数はプログラムの任意に決められます。「無効」では行き先別分配をしなくなります。 ###length 3 @@ -2809,11 +2809,11 @@ STR_LANDSCAPING_TOOLBAR :{WHITE}地形 STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND :{BLACK}土地の角を下げます。ドラッグで範囲選択すると最初に選択した土地の高度より一段低い高さに土地をならします。Ctrlで斜めに選択できます。またShiftを押しながら決定すると工事費用を見積もります STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND :{BLACK}土地の角を上げます。ドラッグで範囲選択すると最初に選択した土地の高度より一段高い高さに土地をならします。Ctrlで斜めに選択できます。またShiftを押しながら決定すると工事費用を見積もります STR_LANDSCAPING_LEVEL_LAND_TOOLTIP :{BLACK}最初に選択した土地の高さに選択範囲をならします。Ctrlで斜めに選択できます。またShiftを押しながら決定すると工事費用を見積もります -STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND :{BLACK}将来用に土地を購入します。Shiftを押しながら決定すると費用を見積もります +STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND :{BLACK}将来用に土地を購入します。Ctrlで斜めに選択できます。Shiftを押しながら決定すると費用を見積もります # Object construction window STR_OBJECT_BUILD_CAPTION :{WHITE}オブジェクトを配置 -STR_OBJECT_BUILD_TOOLTIP :{BLACK}設置するオブジェクトを選択して下さい。Shift+クリックで費用を見積もります +STR_OBJECT_BUILD_TOOLTIP :{BLACK}設置するオブジェクトを選択して下さい。Ctrlで斜めに選択できます。Shift+クリックで費用を見積もります STR_OBJECT_BUILD_CLASS_TOOLTIP :{BLACK}設置するオブジェクトを選びます STR_OBJECT_BUILD_PREVIEW_TOOLTIP :{BLACK}オブジェクトをプレビューします STR_OBJECT_BUILD_SIZE :{BLACK}サイズ: {GOLD}{NUM} x {NUM} マス @@ -2825,7 +2825,7 @@ STR_OBJECT_CLASS_TRNS :電波塔 STR_PLANT_TREE_CAPTION :{WHITE}植林 STR_PLANT_TREE_TOOLTIP :{BLACK}植林する樹類を選択します。既に木がある場合は追加で植林されます STR_TREES_RANDOM_TYPE :{BLACK}ランダムな樹類 -STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}ランダムな樹類で植林します。Shift+クリックで費用を見積もります +STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}ランダムな樹類で植林します。Ctrlで斜めに選択できます。Shift+クリックで費用を見積もります STR_TREES_RANDOM_TREES_BUTTON :{BLACK}ランダムに広域植林 STR_TREES_RANDOM_TREES_TOOLTIP :{BLACK}地表全体にランダムに植林します STR_TREES_MODE_NORMAL_BUTTON :{BLACK}普通 @@ -3496,14 +3496,14 @@ STR_LOCAL_AUTHORITY_ACTION_EXCLUSIVE_TRANSPORT :独占運送契 STR_LOCAL_AUTHORITY_ACTION_BRIBE :議会を買収 ###length 8 -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{YELLOW}旅客と貨物を確保する為に、街で新聞広告を実施します。{}より多くの旅客と貨物が自社の交通網を利用するようになります。{}費用: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{YELLOW}旅客と貨物を確保する為に、街でラジオCMを実施します{}街の中心部から中範囲にある駅の評価が一時的に高まります。{}費用: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{YELLOW}旅客と貨物を確保する為に、街でTV-CMを開始します{}街の中心部の大範囲にある駅の評価が一時的に高まります。{}費用: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{YELLOW}街内の道路補修工事に出資します。最高6ヶ月間街中の道路交通が途絶します。{}費用: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{YELLOW}社を称える彫像を建設します{}この街の駅の評価を恒久的に高めます。{}費用: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW}市街地の開発に出資します{}街の成長速度が一時的に早まります。{}費用: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW}街と一年間の独占運送契約を締結します。{}乗客や貨物はあなたの会社の運送経路のみを使用するようになります。{} 費用: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW}買収を行い、議会内の評判を高めます。注意: 露見した場合は処罰されます{} 費用: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{PUSH_COLOUR}{YELLOW}旅客と貨物を確保する為に、街で新聞広告を実施します。{}より多くの旅客と貨物が自社の交通網を利用するようになります。{}{POP_COLOUR}費用: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{PUSH_COLOUR}{YELLOW}旅客と貨物を確保する為に、街でラジオCMを実施します{}街の中心部から中範囲にある駅の評価が一時的に高まります。{}{POP_COLOUR}費用: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{PUSH_COLOUR}{YELLOW}旅客と貨物を確保する為に、街でTV-CMを開始します{}街の中心部の大範囲にある駅の評価が一時的に高まります。{}{POP_COLOUR}費用: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{PUSH_COLOUR}{YELLOW}街内の道路補修工事に出資します。{}最高6ヶ月間街中の道路交通が途絶します。{}{POP_COLOUR}費用: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{PUSH_COLOUR}{YELLOW}社を称える彫像を建設します{}この街の駅の評価を恒久的に高めます。{}{POP_COLOUR}費用: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{PUSH_COLOUR}{YELLOW}市街地の開発に出資します{}街の成長速度が一時的に早まります。{}{POP_COLOUR}費用: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{PUSH_COLOUR}{YELLOW}街と一年間の独占運送契約を締結します。{}乗客や貨物はあなたの会社の運送経路のみを使用するようになります。{}{POP_COLOUR}費用: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{PUSH_COLOUR}{YELLOW}買収を行い、議会内の評判を高めます。注意: 露見した場合は処罰されます{}{POP_COLOUR}費用: {CURRENCY_LONG} # Goal window STR_GOALS_CAPTION :{WHITE}{COMPANY} 目標 @@ -4084,7 +4084,7 @@ STR_ENGINE_PREVIEW_AIRCRAFT :航空機 STR_ENGINE_PREVIEW_SHIP :船舶 STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER :{BLACK}費用: {CURRENCY_LONG} 重量: {WEIGHT_SHORT}{} 最高速度: {VELOCITY} 出力: {POWER}{} 維持費: {CURRENCY_LONG} /年{} 容量: {CARGO_LONG} -STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}価格: {CURRENCY_LONG} 重量: {WEIGHT_SHORT}{}最高速度: {VELOCITY} 出力: {POWER} 最大牽引力: {6:FORCE}{}運用費: {4:CURRENCY_LONG}/年{}収容量 {5:CARGO_LONG} +STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}価格: {0:CURRENCY_LONG} 重量: {1:WEIGHT_SHORT}{}最高速度: {2:VELOCITY} 出力: {3:POWER} 最大牽引力: {6:FORCE}{}運用費: {4:CURRENCY_LONG}/年{}収容量 {5:CARGO_LONG} STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST :{BLACK}費用: {CURRENCY_LONG} 最高速度: {VELOCITY}{} 容量: {CARGO_LONG}{} 維持費: {CURRENCY_LONG} /年 STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_CAP_RUNCOST :{BLACK}費用: {CURRENCY_LONG} 最高速度: {VELOCITY}{} 航空機の種類: {STRING}{} 容量: {CARGO_LONG}, {CARGO_LONG}{} 維持費: {CURRENCY_LONG}/yr STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_RUNCOST :{BLACK}費用: {CURRENCY_LONG} 最高速度: {VELOCITY}{} 航空機の種類: {STRING}{} 容量: {CARGO_LONG}{} 維持費: {CURRENCY_LONG} /年 @@ -4401,7 +4401,7 @@ STR_ORDERS_DELETE_BUTTON :{BLACK}削除 STR_ORDERS_DELETE_TOOLTIP :{BLACK}選択した指令を削除します STR_ORDERS_DELETE_ALL_TOOLTIP :{BLACK}指令をすべて除去 STR_ORDERS_STOP_SHARING_BUTTON :{BLACK}共有を解除 -STR_ORDERS_STOP_SHARING_TOOLTIP :{BLACK}指令の共有を解除します。Ctrl+クリックで全司令を消去します +STR_ORDERS_STOP_SHARING_TOOLTIP :{BLACK}指令の共有を解除します。Ctrl+クリックで全指令を消去します STR_ORDERS_GO_TO_BUTTON :{BLACK}移動先を選択 STR_ORDER_GO_TO_NEAREST_DEPOT :最寄りの車両庫へ向かう @@ -4518,19 +4518,19 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}始発 STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}始発日時を設定します。Ctrl+クリックでは、指令を共有する輸送機器があり、ダイヤが完全に組まれている場合に限り、その総所要時間に基づき、各輸送機器に指定時刻から均等に始発日時を割り付けます STR_TIMETABLE_CHANGE_TIME :{BLACK}時間を変更 -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}選択した指令の行程時間を変更します +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}選択した指令の行程時間を変更します。Ctrl+クリックで全指令に適用します STR_TIMETABLE_CLEAR_TIME :{BLACK}時刻を消去 -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}選択した指令の行程時間を消去します +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}選択した指令の行程時間を消去します。Ctrl+クリックで全指令に適用します STR_TIMETABLE_CHANGE_SPEED :{BLACK}制限速度を変更 -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}選択した移動区間での最高速度を設定します +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}選択した移動区間での最高速度を変更します。Ctrl+クリックですべての移動区間に適用します STR_TIMETABLE_CLEAR_SPEED :{BLACK}制限速度を撤廃 -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}選択した移動区間にある最高速度を撤廃します +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}選択した移動区間にある最高速度を撤廃します。Ctrl+クリックですべての移動区間に適用します STR_TIMETABLE_RESET_LATENESS :{BLACK}遅延をリセット -STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}ダイヤからの遅延量をリセットして、現状を定刻にします +STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}ダイヤからの遅延量をリセットして、現状を定刻にします。Ctrl+クリックでグループ内で最も遅延している輸送機器を時間通りにして、その他の輸送機器を早着状態にします STR_TIMETABLE_AUTOFILL :{BLACK}オートフィル STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}実際に各指令が実行された時の所要時間を収集してダイヤを作成します。Ctrl+クリックでは既存の停車時間は維持して移動時間のみ更新します(輸送機器を上位モデルに置き換えたときに便利です) @@ -5091,6 +5091,9 @@ STR_ERROR_NO_BUS_STATION :{WHITE}バス STR_ERROR_NO_TRUCK_STATION :{WHITE}荷役所がありません STR_ERROR_NO_DOCK :{WHITE}埠頭がありません STR_ERROR_NO_AIRPORT :{WHITE}空港・ヘリポートがありません +STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE :{WHITE}バスに対応する停留所がありません +STR_ERROR_NO_STOP_COMPATIBLE_TRAM_TYPE :{WHITE}路面電車に対応する停留所がありません +STR_ERROR_NO_STOP_ARTICULATED_VEHICLE :{WHITE}連結式車両が停まれるバス停がありません。{}路側型バス停が必要です。 STR_ERROR_AIRPORT_NO_PLANES :{WHITE}この飛行機はこのヘリポートに着陸できません STR_ERROR_AIRPORT_NO_HELICOPTERS :{WHITE}このヘリコプターはこの空港に着陸できません STR_ERROR_NO_RAIL_WAYPOINT :{WHITE}中継駅がありません diff --git a/src/lang/simplified_chinese.txt b/src/lang/simplified_chinese.txt index 83a395d774..0c7b27a505 100644 --- a/src/lang/simplified_chinese.txt +++ b/src/lang/simplified_chinese.txt @@ -2358,6 +2358,7 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(新公司) STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}新建并加入公司 STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}这是你 STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}这里是游戏的主机 +STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT_TOOLTIP :{BLACK}服务器管理员允许的当前连接的玩家数量、公司数量和最多公司数量 # Matches ConnectionType ###length 5 @@ -3351,6 +3352,7 @@ STR_NEWGRF_ERROR_MSG_INFO :{SILVER}{STRING STR_NEWGRF_ERROR_MSG_WARNING :{RED}警告:{SILVER}{STRING} STR_NEWGRF_ERROR_MSG_ERROR :{RED}错误:{SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}严重错误:{SILVER}{STRING} +STR_NEWGRF_ERROR_POPUP :{WHITE}NewGRF "{STRING}"发生了一个错误:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} 不能与 OpenTTD 报告的 TTDPatch 版本兼容。 STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} 是为 {2:STRING} 版 TTD 开发的。 STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} 应当与 {2:STRING} 配合 @@ -5082,6 +5084,16 @@ STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION :{WHITE}…… STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE :{WHITE}... 飞机航行距离不足 # Extra messages which go on the third line of errors, explaining why orders failed +STR_ERROR_NO_RAIL_STATION :{WHITE}没有火车站 +STR_ERROR_NO_BUS_STATION :{WHITE}没有公交车站 +STR_ERROR_NO_DOCK :{WHITE}这里没有码头 +STR_ERROR_NO_AIRPORT :{WHITE}没有机场/直升机场 +STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE :{WHITE}没有兼容此道路类型的站点 +STR_ERROR_NO_STOP_COMPATIBLE_TRAM_TYPE :{WHITE}没有兼容此有轨电车道路类型的站点 +STR_ERROR_NO_STOP_ARTICULATED_VEHICLE :{WHITE}没有适合铰接式道路车辆的站点.{}铰接式道路车辆需要通过式车站,而不是港湾式车站 +STR_ERROR_AIRPORT_NO_PLANES :{WHITE}这架飞机不能降落在这个直升机场 +STR_ERROR_AIRPORT_NO_HELICOPTERS :{WHITE}这架直升机不能降落在这个机场 +STR_ERROR_NO_RAIL_WAYPOINT :{WHITE}没有铁路路点 # Timetable related errors STR_ERROR_CAN_T_TIMETABLE_VEHICLE :{WHITE}不能给车辆编制时间表… From 066ae6f3fb1fba1931b3d711f330f4cf389644ea Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Sat, 25 Mar 2023 15:40:59 -0400 Subject: [PATCH 02/13] Codechange: Simplify some CodeQL-flagged trivial switches --- src/gamelog.cpp | 9 +++------ src/misc_gui.cpp | 9 +++------ src/object_gui.cpp | 23 ++++++++++------------- src/toolbar_gui.cpp | 4 +--- src/video/opengl.cpp | 24 ++++++++---------------- 5 files changed, 25 insertions(+), 44 deletions(-) diff --git a/src/gamelog.cpp b/src/gamelog.cpp index 0e251aae00..0346134c19 100644 --- a/src/gamelog.cpp +++ b/src/gamelog.cpp @@ -328,12 +328,9 @@ void GamelogPrint(std::function proc) case GLCT_GRFBUG: { /* A specific bug in a NewGRF, that could cause wide spread problems, has been noted during the execution of the game. */ GrfIDMapping::Pair *gm = grf_names.Find(lc->grfrem.grfid); - switch (lc->grfbug.bug) { - default: NOT_REACHED(); - case GBUG_VEH_LENGTH: - buf += seprintf(buf, lastof(buffer), "Rail vehicle changes length outside a depot: GRF ID %08X, internal ID 0x%X", BSWAP32(lc->grfbug.grfid), (uint)lc->grfbug.data); - break; - } + assert (lc->grfbug.bug == GBUG_VEH_LENGTH); + + buf += seprintf(buf, lastof(buffer), "Rail vehicle changes length outside a depot: GRF ID %08X, internal ID 0x%X", BSWAP32(lc->grfbug.grfid), (uint)lc->grfbug.data); buf = PrintGrfInfo(buf, lastof(buffer), lc->grfbug.grfid, nullptr, gm != grf_names.End() ? gm->second.gc : nullptr); if (gm == grf_names.End()) buf += seprintf(buf, lastof(buffer), ". Gamelog inconsistency: GrfID was never added!"); break; diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 896708b77a..e67e91c785 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -360,12 +360,9 @@ public: void OnInvalidateData(int data = 0, bool gui_scope = true) override { if (!gui_scope) return; - switch (data) { - case 1: - /* ReInit, "debug" sprite might have changed */ - this->ReInit(); - break; - } + + /* ReInit, "debug" sprite might have changed */ + if (data == 1) this->ReInit(); } }; diff --git a/src/object_gui.cpp b/src/object_gui.cpp index f45f2ae426..7fb8e93c6f 100644 --- a/src/object_gui.cpp +++ b/src/object_gui.cpp @@ -565,20 +565,17 @@ public: { if (pt.x == -1) return; - switch (select_proc) { - default: NOT_REACHED(); - case DDSP_BUILD_OBJECT: - if (!_settings_game.construction.freeform_edges) { - /* When end_tile is MP_VOID, the error tile will not be visible to the - * user. This happens when terraforming at the southern border. */ - if (TileX(end_tile) == Map::MaxX()) end_tile += TileDiffXY(-1, 0); - if (TileY(end_tile) == Map::MaxY()) end_tile += TileDiffXY(0, -1); - } - const ObjectSpec *spec = ObjectClass::Get(_selected_object_class)->GetSpec(_selected_object_index); - Command::Post(STR_ERROR_CAN_T_BUILD_OBJECT, CcPlaySound_CONSTRUCTION_OTHER, - end_tile, start_tile, spec->Index(), _selected_object_view, (_ctrl_pressed ? true : false)); - break; + assert(select_proc == DDSP_BUILD_OBJECT); + + if (!_settings_game.construction.freeform_edges) { + /* When end_tile is MP_VOID, the error tile will not be visible to the + * user. This happens when terraforming at the southern border. */ + if (TileX(end_tile) == Map::MaxX()) end_tile += TileDiffXY(-1, 0); + if (TileY(end_tile) == Map::MaxY()) end_tile += TileDiffXY(0, -1); } + const ObjectSpec *spec = ObjectClass::Get(_selected_object_class)->GetSpec(_selected_object_index); + Command::Post(STR_ERROR_CAN_T_BUILD_OBJECT, CcPlaySound_CONSTRUCTION_OTHER, + end_tile, start_tile, spec->Index(), _selected_object_view, (_ctrl_pressed ? true : false)); } void OnPlaceObjectAbort() override diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index d03371d428..554adf9ba5 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -552,9 +552,7 @@ static CallBackFunction ToolbarSubsidiesClick(Window *w) */ static CallBackFunction MenuClickSubsidies(int index) { - switch (index) { - case 0: ShowSubsidiesList(); break; - } + ShowSubsidiesList(); return CBF_NONE; } diff --git a/src/video/opengl.cpp b/src/video/opengl.cpp index ae46fe78f0..862dbf8da1 100644 --- a/src/video/opengl.cpp +++ b/src/video/opengl.cpp @@ -955,14 +955,10 @@ bool OpenGLBackend::Resize(int w, int h, bool force) _glActiveTexture(GL_TEXTURE0); _glBindTexture(GL_TEXTURE_2D, this->vid_texture); - switch (bpp) { - case 8: - _glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr); - break; - - default: - _glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr); - break; + if (bpp == 8) { + _glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr); + } else { + _glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr); } _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); @@ -1224,14 +1220,10 @@ void OpenGLBackend::ReleaseVideoBuffer(const Rect &update_rect) _glActiveTexture(GL_TEXTURE0); _glBindTexture(GL_TEXTURE_2D, this->vid_texture); _glPixelStorei(GL_UNPACK_ROW_LENGTH, _screen.pitch); - switch (BlitterFactory::GetCurrentBlitter()->GetScreenDepth()) { - case 8: - _glTexSubImage2D(GL_TEXTURE_2D, 0, update_rect.left, update_rect.top, update_rect.right - update_rect.left, update_rect.bottom - update_rect.top, GL_RED, GL_UNSIGNED_BYTE, (GLvoid *)(size_t)(update_rect.top * _screen.pitch + update_rect.left)); - break; - - default: - _glTexSubImage2D(GL_TEXTURE_2D, 0, update_rect.left, update_rect.top, update_rect.right - update_rect.left, update_rect.bottom - update_rect.top, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, (GLvoid *)(size_t)(update_rect.top * _screen.pitch * 4 + update_rect.left * 4)); - break; + if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 8) { + _glTexSubImage2D(GL_TEXTURE_2D, 0, update_rect.left, update_rect.top, update_rect.right - update_rect.left, update_rect.bottom - update_rect.top, GL_RED, GL_UNSIGNED_BYTE, (GLvoid*)(size_t)(update_rect.top * _screen.pitch + update_rect.left)); + } else { + _glTexSubImage2D(GL_TEXTURE_2D, 0, update_rect.left, update_rect.top, update_rect.right - update_rect.left, update_rect.bottom - update_rect.top, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, (GLvoid*)(size_t)(update_rect.top * _screen.pitch * 4 + update_rect.left * 4)); } #ifndef NO_GL_BUFFER_SYNC From 0bf6f823051b6adf02df06d47cf8212e0e5a1f02 Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Sat, 25 Mar 2023 15:59:48 -0400 Subject: [PATCH 03/13] Cleanup: Don't mix switches and early returns in widget selection --- src/newgrf_debug_gui.cpp | 93 ++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 38 deletions(-) diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index 764fd995cf..c7176f6bdd 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -406,49 +406,53 @@ struct NewGRFInspectWindow : Window { ::DrawString(r.Shrink(WidgetDimensions::scaled.frametext).Shrink(0, offset * this->resize.step_height, 0, 0), buf, TC_BLACK); } - void DrawWidget(const Rect &r, int widget) const override + /** + * Helper function to draw the vehicle chain widget. + * @param r The rectangle to draw within. + */ + void DrawVehicleChainWidget(const Rect& r) const { - switch (widget) { - case WID_NGRFI_VEH_CHAIN: { - const Vehicle *v = Vehicle::Get(this->GetFeatureIndex()); - int total_width = 0; - int sel_start = 0; - int sel_end = 0; - for (const Vehicle *u = v->First(); u != nullptr; u = u->Next()) { - if (u == v) sel_start = total_width; - switch (u->type) { - case VEH_TRAIN: total_width += Train ::From(u)->GetDisplayImageWidth(); break; - case VEH_ROAD: total_width += RoadVehicle::From(u)->GetDisplayImageWidth(); break; - default: NOT_REACHED(); - } - if (u == v) sel_end = total_width; - } - - Rect br = r.Shrink(WidgetDimensions::scaled.bevel); - int width = br.Width(); - int skip = 0; - if (total_width > width) { - int sel_center = (sel_start + sel_end) / 2; - if (sel_center > width / 2) skip = std::min(total_width - width, sel_center - width / 2); - } - - GrfSpecFeature f = GetFeatureNum(this->window_number); - int h = GetVehicleImageCellSize((VehicleType)(VEH_TRAIN + (f - GSF_TRAINS)), EIT_IN_DEPOT).height; - int y = CenterBounds(br.top, br.bottom, h); - DrawVehicleImage(v->First(), br, INVALID_VEHICLE, EIT_IN_DETAILS, skip); - - /* Highlight the articulated part (this is different to the whole-vehicle highlighting of DrawVehicleImage */ - if (_current_text_dir == TD_RTL) { - DrawFrameRect(r.right - sel_end + skip, y, r.right - sel_start + skip, y + h, COLOUR_WHITE, FR_BORDERONLY); - } else { - DrawFrameRect(r.left + sel_start - skip, y, r.left + sel_end - skip, y + h, COLOUR_WHITE, FR_BORDERONLY); - } - break; + const Vehicle *v = Vehicle::Get(this->GetFeatureIndex()); + int total_width = 0; + int sel_start = 0; + int sel_end = 0; + for (const Vehicle *u = v->First(); u != nullptr; u = u->Next()) { + if (u == v) sel_start = total_width; + switch (u->type) { + case VEH_TRAIN: total_width += Train::From(u)->GetDisplayImageWidth(); break; + case VEH_ROAD: total_width += RoadVehicle::From(u)->GetDisplayImageWidth(); break; + default: NOT_REACHED(); } + if (u == v) sel_end = total_width; + } + + Rect br = r.Shrink(WidgetDimensions::scaled.bevel); + int width = br.Width(); + int skip = 0; + if (total_width > width) { + int sel_center = (sel_start + sel_end) / 2; + if (sel_center > width / 2) skip = std::min(total_width - width, sel_center - width / 2); } - if (widget != WID_NGRFI_MAINPANEL) return; + GrfSpecFeature f = GetFeatureNum(this->window_number); + int h = GetVehicleImageCellSize((VehicleType)(VEH_TRAIN + (f - GSF_TRAINS)), EIT_IN_DEPOT).height; + int y = CenterBounds(br.top, br.bottom, h); + DrawVehicleImage(v->First(), br, INVALID_VEHICLE, EIT_IN_DETAILS, skip); + + /* Highlight the articulated part (this is different to the whole-vehicle highlighting of DrawVehicleImage */ + if (_current_text_dir == TD_RTL) { + DrawFrameRect(r.right - sel_end + skip, y, r.right - sel_start + skip, y + h, COLOUR_WHITE, FR_BORDERONLY); + } else { + DrawFrameRect(r.left + sel_start - skip, y, r.left + sel_end - skip, y + h, COLOUR_WHITE, FR_BORDERONLY); + } + } + /** + * Helper function to draw the main panel widget. + * @param r The rectangle to draw within. + */ + void DrawMainPanelWidget(const Rect& r) const + { uint index = this->GetFeatureIndex(); const NIFeature *nif = GetFeature(this->window_number); const NIHelper *nih = nif->helper; @@ -547,6 +551,19 @@ struct NewGRFInspectWindow : Window { const_cast(this)->vscroll->SetCount(i); } + void DrawWidget(const Rect &r, int widget) const override + { + switch (widget) { + case WID_NGRFI_VEH_CHAIN: + this->DrawVehicleChainWidget(r); + break; + + case WID_NGRFI_MAINPANEL: + this->DrawMainPanelWidget(r); + break; + } + } + void OnClick(Point pt, int widget, int click_count) override { switch (widget) { From 9642e87bc8dd7874d60baec3bf6798de8fa525ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Sat, 25 Mar 2023 23:07:47 +0100 Subject: [PATCH 04/13] Fix: [Script] Access to enum/consts defined outside of main.nut (#10573) --- src/script/squirrel.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/script/squirrel.cpp b/src/script/squirrel.cpp index 2485ed791a..a57d364fb4 100644 --- a/src/script/squirrel.cpp +++ b/src/script/squirrel.cpp @@ -566,6 +566,10 @@ void Squirrel::Initialize() sq_pushroottable(this->vm); squirrel_register_global_std(this); + + /* Set consts table as delegate of root table, so consts/enums defined via require() are accessible */ + sq_pushconsttable(this->vm); + sq_setdelegate(this->vm, -2); } class SQFile { @@ -764,6 +768,12 @@ void Squirrel::Uninitialize() { ScriptAllocatorScope alloc_scope(this); + /* Remove the delegation */ + sq_pushroottable(this->vm); + sq_pushnull(this->vm); + sq_setdelegate(this->vm, -2); + sq_pop(this->vm, 1); + /* Clean up the stuff */ sq_pop(this->vm, 1); sq_close(this->vm); From 3611082f8ebc6f1cc461c770780b32cddbc863c0 Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Sun, 26 Mar 2023 03:35:44 -0400 Subject: [PATCH 05/13] Codechange: [CodeQL] Disable CodeQL check on trivial switch statements (#10537) --- .github/codeql/codeql-config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index e5bd27659c..b5fd9c58ed 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -8,3 +8,5 @@ query-filters: - cpp/world-writable-file-creation # Basically OpenTTD's coding style for adding things like ..._INVALID to enumerations - 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 From e26d3de5fbcf77b910fe055b7a93050fbe4582d3 Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Sun, 26 Mar 2023 05:08:37 -0400 Subject: [PATCH 06/13] Doc: Add guide to releasing OpenTTD (#10563) --- docs/releasing_openttd.md | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 docs/releasing_openttd.md diff --git a/docs/releasing_openttd.md b/docs/releasing_openttd.md new file mode 100644 index 0000000000..acb3ad9bc7 --- /dev/null +++ b/docs/releasing_openttd.md @@ -0,0 +1,48 @@ +# Releasing OpenTTD + +This guide is for OpenTTD developers/maintainers, to release a new version of OpenTTD. + +## Step 0: Branch or Backport + +* If this is a beta version release, skip this step. + +* If this is an RC1 (first Release Candidate) build, create a new branch `release/nn` where `nn` is the major version number, then apply changes similar to [PR#9573](https://github.com/OpenTTD/OpenTTD/pull/9573). You also need to forwardport the changelog, as in [PR#10113](https://github.com/OpenTTD/OpenTTD/pull/10113). + * Update CMakeLists.txt + * Add a new (empty) AI compatibility script in bin/ai/ + * Add the new version to CheckAPIVersion in src/ai/ai_info.cpp + src/game/game_info.cpp + * Add the new version to src/script/api/ai_changelog.hpp + src/script/api/game_changelog.hpp + * Update the version of regression in bin/ai/regression/regression_info.nut + * Add a note to src/saveload/saveload.h about which savegame version is used in the branch. + +* If this is a later RC or release build and the release branch already exists, you'll need to backport fixes and language from master to this branch, which were merged after the branch diverged from master. You can use these two helper scripts: https://github.com/OpenTTD/scripts/tree/main/backport + +## Step 1: Prepare changelog documentation + +1. Update the [changelog](../changelog.txt) with new changes since the last release. + * Changelog entries are typically PR titles, but can be edited to be more helpful without context. + * Don't include fixes to things which haven't previously been released (like fixes to features which are in the same changelog). + * Order the entries by importance: `Feature > Add > Change > Fix`, then numerically by PR number. +2. Create a changelog PR, get approval, and merge. + * For beta releases, target master, otherwise target the release branch. + +## Step 2: Prepare website release announcement + +1. Go to https://github.com/OpenTTD/website/new/main/_posts and write a new announcement post. See a [previous example](https://github.com/OpenTTD/website/pull/238) for a template. +2. Create a new branch for this post and open a PR for it. +3. Write announcement text for socials like Forum/Discord/Twitter/Reddit and include it in the PR. +4. Create a Steam news image for that post and include it in the PR. +5. Check the website post (preview link via checks page) and make corrections. We usually just use the GitHub web interface for this and squash the result later. +6. Get this PR approved, but do not merge yet. + +## Step 3: Make the actual OpenTTD release + +1. Go to https://github.com/OpenTTD/OpenTTD/releases/new and create a new tag matching the release number. For the body of the release, see any older release. "Set as a pre-release" for a beta or RC, set as latest for a real release. +2. Merge website PR. +3. Wait for the OpenTTD release checks to be complete. +4. Check that website links to the new release are working and correct, using the [staging website](https://www-staging.openttd.org/). +5. If this is a full release, ask orudge to update the Microsoft Store and TrueBrain to move the release from the "testing" to "default" branch on Steam. + +## Step 4: Tell the world + +1. Tag and create a website release to trigger the actions that update the website. +2. After the website is live, make announcements on social media. You may need to coordinate with other developers who can make posts on Twitter, Reddit, Steam, and GOG. From c9058242484bbee61e272c99997823f83b8eadba Mon Sep 17 00:00:00 2001 From: translators Date: Tue, 28 Mar 2023 18:43:33 +0000 Subject: [PATCH 07/13] Update: Translations from eints chinese (traditional): 14 changes by inAndyPao danish: 1 change by bscargo --- src/lang/danish.txt | 2 +- src/lang/traditional_chinese.txt | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/lang/danish.txt b/src/lang/danish.txt index da7c5ea5db..c0d41d8b49 100644 --- a/src/lang/danish.txt +++ b/src/lang/danish.txt @@ -2791,7 +2791,7 @@ STR_AIRPORT_SMALL :Lille STR_AIRPORT_CITY :By STR_AIRPORT_METRO :Metropollufthavn STR_AIRPORT_INTERNATIONAL :International lufthavn -STR_AIRPORT_COMMUTER :Pendler +STR_AIRPORT_COMMUTER :Pendler lufthavn STR_AIRPORT_INTERCONTINENTAL :Interkontinental STR_AIRPORT_HELIPORT :Helikopterlandingsplads STR_AIRPORT_HELIDEPOT :Helikopterværksted diff --git a/src/lang/traditional_chinese.txt b/src/lang/traditional_chinese.txt index b50cd51c0a..6fe2bc4a92 100644 --- a/src/lang/traditional_chinese.txt +++ b/src/lang/traditional_chinese.txt @@ -2358,6 +2358,8 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(新公司) STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}創立並加入一個新公司 STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}這是你 STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}這是遊戲的主持端 +STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM}個用戶端 {NUM}/{NUM}所公司 +STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT_TOOLTIP :{BLACK}目前已連線客戶端的數量、公司數量,以及伺服器管理員所允許的最大公司數量 # Matches ConnectionType ###length 5 @@ -5084,6 +5086,18 @@ STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION :{WHITE}... 與 STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE :{WHITE}... 飛機的飛行範圍不足 # Extra messages which go on the third line of errors, explaining why orders failed +STR_ERROR_NO_RAIL_STATION :{WHITE}沒有火車站 +STR_ERROR_NO_BUS_STATION :{WHITE}沒有公車站 +STR_ERROR_NO_TRUCK_STATION :{WHITE}沒有貨車站 +STR_ERROR_NO_DOCK :{WHITE}這裡沒有碼頭 +STR_ERROR_NO_AIRPORT :{WHITE}沒有機場/直昇機場 +STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE :{WHITE}沒有兼容此道路類型的站點 +STR_ERROR_NO_STOP_COMPATIBLE_TRAM_TYPE :{WHITE}沒有兼容此有軌電車道路類型的站點 +STR_ERROR_NO_STOP_ARTICULATED_VEHICLE :{WHITE}沒有適合聯結式公路車的停車站.{}聯結式公路車需要通過式的停車站,而非港式的停車站 +STR_ERROR_AIRPORT_NO_PLANES :{WHITE}這架飛機不能降落在這個直昇機場 +STR_ERROR_AIRPORT_NO_HELICOPTERS :{WHITE}這架直昇機不能降落在這個機場 +STR_ERROR_NO_RAIL_WAYPOINT :{WHITE}沒有鐵路路點 +STR_ERROR_NO_BUOY :{WHITE}沒有浮標 # Timetable related errors STR_ERROR_CAN_T_TIMETABLE_VEHICLE :{WHITE}無法為車輛加入時刻表... From c1077212d769a3e9472b948ae721efbc0d4cda84 Mon Sep 17 00:00:00 2001 From: PeterN Date: Fri, 31 Mar 2023 16:06:36 +0100 Subject: [PATCH 08/13] Codechange: Use a shared_ptr for viewport overlay. (#10586) --- src/linkgraph/linkgraph_gui.cpp | 2 +- src/linkgraph/linkgraph_gui.h | 4 ++-- src/main_gui.cpp | 2 +- src/viewport.cpp | 7 ++----- src/viewport_type.h | 2 +- 5 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/linkgraph/linkgraph_gui.cpp b/src/linkgraph/linkgraph_gui.cpp index 026f85b853..b000ae5cc3 100644 --- a/src/linkgraph/linkgraph_gui.cpp +++ b/src/linkgraph/linkgraph_gui.cpp @@ -562,7 +562,7 @@ LinkGraphLegendWindow::LinkGraphLegendWindow(WindowDesc *desc, int window_number * Set the overlay belonging to this menu and import its company/cargo settings. * @param overlay New overlay for this menu. */ -void LinkGraphLegendWindow::SetOverlay(LinkGraphOverlay *overlay) { +void LinkGraphLegendWindow::SetOverlay(std::shared_ptr overlay) { this->overlay = overlay; uint32 companies = this->overlay->GetCompanyMask(); for (uint c = 0; c < MAX_COMPANIES; c++) { diff --git a/src/linkgraph/linkgraph_gui.h b/src/linkgraph/linkgraph_gui.h index ef249b9bfd..2d3c2baaff 100644 --- a/src/linkgraph/linkgraph_gui.h +++ b/src/linkgraph/linkgraph_gui.h @@ -108,7 +108,7 @@ void ShowLinkGraphLegend(); struct LinkGraphLegendWindow : Window { public: LinkGraphLegendWindow(WindowDesc *desc, int window_number); - void SetOverlay(LinkGraphOverlay *overlay); + void SetOverlay(std::shared_ptr overlay); void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override; void DrawWidget(const Rect &r, int widget) const override; @@ -117,7 +117,7 @@ public: void OnInvalidateData(int data = 0, bool gui_scope = true) override; private: - LinkGraphOverlay *overlay; + std::shared_ptr overlay; void UpdateOverlayCompanies(); void UpdateOverlayCargoes(); diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 05ee75d2f3..bdecd07ba5 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -224,7 +224,7 @@ struct MainWindow : Window NWidgetViewport *nvp = this->GetWidget(WID_M_VIEWPORT); nvp->InitializeViewport(this, TileXY(32, 32), ScaleZoomGUI(ZOOM_LVL_VIEWPORT)); - this->viewport->overlay = new LinkGraphOverlay(this, WID_M_VIEWPORT, 0, 0, 2); + this->viewport->overlay = std::make_shared(this, WID_M_VIEWPORT, 0, 0, 2); this->refresh.SetInterval(LINKGRAPH_DELAY); } diff --git a/src/viewport.cpp b/src/viewport.cpp index dd5e469085..79fc0da175 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -203,10 +203,7 @@ static Point MapXYZToViewport(const Viewport *vp, int x, int y, int z) void DeleteWindowViewport(Window *w) { - if (w->viewport == nullptr) return; - - delete w->viewport->overlay; - free(w->viewport); + delete w->viewport; w->viewport = nullptr; } @@ -227,7 +224,7 @@ void InitializeWindowViewport(Window *w, int x, int y, { assert(w->viewport == nullptr); - ViewportData *vp = CallocT(1); + ViewportData *vp = new ViewportData(); vp->left = x + w->left; vp->top = y + w->top; diff --git a/src/viewport_type.h b/src/viewport_type.h index 5200514403..dc610d1686 100644 --- a/src/viewport_type.h +++ b/src/viewport_type.h @@ -31,7 +31,7 @@ struct Viewport { int virtual_height; ///< height << zoom ZoomLevel zoom; ///< The zoom level of the viewport. - LinkGraphOverlay *overlay; + std::shared_ptr overlay; }; /** Location information about a sign as seen on the viewport */ From 73474b08fe4c5bd3ffcc4f9a2a8734d83158a2d7 Mon Sep 17 00:00:00 2001 From: PeterN Date: Fri, 31 Mar 2023 16:07:15 +0100 Subject: [PATCH 09/13] Fix: Clicking on editbox clear button didn't take account of padding. (#10583) --- src/misc_gui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index e67e91c785..3f6b03585d 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -932,7 +932,8 @@ void QueryString::ClickEditBox(Window *w, Point pt, int wid, int click_count, bo assert((wi->type & WWT_MASK) == WWT_EDITBOX); bool rtl = _current_text_dir == TD_RTL; - int clearbtn_width = GetSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT).width; + Dimension sprite_size = GetSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT); + int clearbtn_width = sprite_size.width + WidgetDimensions::scaled.imgbtn.Horizontal(); Rect cr = wi->GetCurrentRect().WithWidth(clearbtn_width, !rtl); From 02961fd7af21b2b3fe9f55f47b0f7c89e78a6259 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 8 Jan 2023 15:36:57 +0000 Subject: [PATCH 10/13] Codechange: Use std::vector for NewGRF class lists. --- src/newgrf_class.h | 9 +++++---- src/newgrf_class_func.h | 14 +++++--------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/newgrf_class.h b/src/newgrf_class.h index 4bac546d35..a0073d1dd4 100644 --- a/src/newgrf_class.h +++ b/src/newgrf_class.h @@ -12,15 +12,16 @@ #include "strings_type.h" +#include + /** * Struct containing information relating to NewGRF classes for stations and airports. */ template struct NewGRFClass { private: - uint count; ///< Number of specs in this class. - uint ui_count; ///< Number of specs in this class potentially available to the user. - Tspec **spec; ///< Array of specifications. + uint ui_count; ///< Number of specs in this class potentially available to the user. + std::vector spec; ///< List of specifications. /** * The actual classes. @@ -41,7 +42,7 @@ public: void Insert(Tspec *spec); /** Get the number of allocated specs within the class. */ - uint GetSpecCount() const { return this->count; } + uint GetSpecCount() const { return static_cast(this->spec.size()); } /** Get the number of potentially user-available specs within the class. */ uint GetUISpecCount() const { return this->ui_count; } int GetUIFromIndex(int index) const; diff --git a/src/newgrf_class_func.h b/src/newgrf_class_func.h index f97ba58b95..b6ab8b455c 100644 --- a/src/newgrf_class_func.h +++ b/src/newgrf_class_func.h @@ -28,11 +28,9 @@ DEFINE_NEWGRF_CLASS_METHOD(void)::ResetClass() { this->global_id = 0; this->name = STR_EMPTY; - this->count = 0; this->ui_count = 0; - free(this->spec); - this->spec = nullptr; + this->spec.clear(); } /** Reset the classes, i.e. clear everything. */ @@ -75,12 +73,9 @@ DEFINE_NEWGRF_CLASS_METHOD(Tid)::Allocate(uint32 global_id) */ DEFINE_NEWGRF_CLASS_METHOD(void)::Insert(Tspec *spec) { - uint i = this->count++; - this->spec = ReallocT(this->spec, this->count); + this->spec.push_back(spec); - this->spec[i] = spec; - - if (this->IsUIAvailable(i)) this->ui_count++; + if (this->IsUIAvailable(static_cast(this->spec.size() - 1))) this->ui_count++; } /** @@ -197,7 +192,8 @@ DEFINE_NEWGRF_CLASS_METHOD(const Tspec *)::GetByGrf(uint32 grfid, byte local_id, uint j; for (Tid i = (Tid)0; i < Tmax; i++) { - for (j = 0; j < classes[i].count; j++) { + uint count = static_cast(classes[i].spec.size()); + for (j = 0; j < count; j++) { const Tspec *spec = classes[i].spec[j]; if (spec == nullptr) continue; if (spec->grf_prop.grffile->grfid == grfid && spec->grf_prop.local_id == local_id) { From 93197f58b7d07ac2f732f61625a8e548d9f02471 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Mon, 16 Jan 2023 23:31:31 +0000 Subject: [PATCH 11/13] Codechange: Bind objectspecs to classes once all finalised. --- src/newgrf.cpp | 2 ++ src/newgrf_commons.cpp | 1 - src/newgrf_object.cpp | 27 ++++++++++++++++++--------- src/newgrf_object.h | 2 ++ 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index cda3f4d5d3..b0fb95c30f 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -9518,6 +9518,8 @@ static void FinaliseObjectsArray() } } } + + ObjectSpec::BindToClasses(); } /** diff --git a/src/newgrf_commons.cpp b/src/newgrf_commons.cpp index eb8d3f8c40..071e4a108a 100644 --- a/src/newgrf_commons.cpp +++ b/src/newgrf_commons.cpp @@ -316,7 +316,6 @@ void ObjectOverrideManager::SetEntitySpec(ObjectSpec *spec) /* Now that we know we can use the given id, copy the spec to its final destination. */ memcpy(&_object_specs[type], spec, sizeof(*spec)); - ObjectClass::Assign(&_object_specs[type]); } /** diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp index ccd46e2e92..c7c2c770ee 100644 --- a/src/newgrf_object.cpp +++ b/src/newgrf_object.cpp @@ -90,6 +90,18 @@ uint ObjectSpec::Index() const return this - _object_specs; } +/** + * Tie all ObjectSpecs to their class. + */ +/* static */ void ObjectSpec::BindToClasses() +{ + for (auto &spec : _object_specs) { + if (spec.IsEnabled() && spec.cls_id != INVALID_OBJECT_CLASS) { + ObjectClass::Assign(&spec); + } + } +} + /** This function initialize the spec arrays of objects. */ void ResetObjects() { @@ -104,20 +116,17 @@ void ResetObjects() for (uint16 i = 0; i < lengthof(_original_objects); i++) { _object_specs[i].grf_prop.local_id = i; } + + /* Set class for originals. */ + _object_specs[OBJECT_LIGHTHOUSE].cls_id = ObjectClass::Allocate('LTHS'); + _object_specs[OBJECT_TRANSMITTER].cls_id = ObjectClass::Allocate('TRNS'); } template /* static */ void NewGRFClass::InsertDefaults() { - ObjectClassID cls = ObjectClass::Allocate('LTHS'); - ObjectClass::Get(cls)->name = STR_OBJECT_CLASS_LTHS; - _object_specs[OBJECT_LIGHTHOUSE].cls_id = cls; - ObjectClass::Assign(&_object_specs[OBJECT_LIGHTHOUSE]); - - cls = ObjectClass::Allocate('TRNS'); - ObjectClass::Get(cls)->name = STR_OBJECT_CLASS_TRNS; - _object_specs[OBJECT_TRANSMITTER].cls_id = cls; - ObjectClass::Assign(&_object_specs[OBJECT_TRANSMITTER]); + ObjectClass::Get(ObjectClass::Allocate('LTHS'))->name = STR_OBJECT_CLASS_LTHS; + ObjectClass::Get(ObjectClass::Allocate('TRNS'))->name = STR_OBJECT_CLASS_TRNS; } template diff --git a/src/newgrf_object.h b/src/newgrf_object.h index a441d3ceec..f283e36407 100644 --- a/src/newgrf_object.h +++ b/src/newgrf_object.h @@ -101,6 +101,8 @@ struct ObjectSpec { static const ObjectSpec *Get(ObjectType index); static const ObjectSpec *GetByTile(TileIndex tile); + + static void BindToClasses(); }; /** Object scope resolver. */ From 1f46f080f0c8be459f3fdea2b28d28a34430750a Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 6 Nov 2022 19:21:03 +0000 Subject: [PATCH 12/13] Codechange: Store objectspecs in std::vector instead of flat array. --- src/newgrf_commons.cpp | 5 +++-- src/newgrf_object.cpp | 20 ++++++++++++++------ src/newgrf_object.h | 1 + src/object_cmd.cpp | 8 ++++---- src/object_gui.cpp | 4 ++-- src/script/api/script_objecttype.cpp | 2 +- src/script/api/script_objecttypelist.cpp | 2 +- 7 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/newgrf_commons.cpp b/src/newgrf_commons.cpp index 071e4a108a..2508fa2726 100644 --- a/src/newgrf_commons.cpp +++ b/src/newgrf_commons.cpp @@ -312,10 +312,11 @@ void ObjectOverrideManager::SetEntitySpec(ObjectSpec *spec) return; } - extern ObjectSpec _object_specs[NUM_OBJECTS]; + extern std::vector _object_specs; /* Now that we know we can use the given id, copy the spec to its final destination. */ - memcpy(&_object_specs[type], spec, sizeof(*spec)); + if (type >= _object_specs.size()) _object_specs.resize(type + 1); + _object_specs[type] = *spec; } /** diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp index c7c2c770ee..a14f8d19ae 100644 --- a/src/newgrf_object.cpp +++ b/src/newgrf_object.cpp @@ -29,7 +29,12 @@ ObjectOverrideManager _object_mngr(NEW_OBJECT_OFFSET, NUM_OBJECTS, INVALID_OBJEC extern const ObjectSpec _original_objects[NEW_OBJECT_OFFSET]; /** All the object specifications. */ -ObjectSpec _object_specs[NUM_OBJECTS]; +std::vector _object_specs; + +size_t ObjectSpec::Count() +{ + return _object_specs.size(); +} /** * Get the specification associated with a specific ObjectType. @@ -38,7 +43,11 @@ ObjectSpec _object_specs[NUM_OBJECTS]; */ /* static */ const ObjectSpec *ObjectSpec::Get(ObjectType index) { + /* Empty object if index is out of range -- this might happen if NewGRFs are changed. */ + static ObjectSpec empty = {}; + assert(index < NUM_OBJECTS); + if (index >= _object_specs.size()) return ∅ return &_object_specs[index]; } @@ -87,7 +96,7 @@ bool ObjectSpec::IsAvailable() const */ uint ObjectSpec::Index() const { - return this - _object_specs; + return this - _object_specs.data(); } /** @@ -106,14 +115,13 @@ uint ObjectSpec::Index() const void ResetObjects() { /* Clean the pool. */ - for (uint16 i = 0; i < NUM_OBJECTS; i++) { - _object_specs[i] = {}; - } + _object_specs.clear(); /* And add our originals. */ - MemCpyT(_object_specs, _original_objects, lengthof(_original_objects)); + _object_specs.resize(lengthof(_original_objects)); for (uint16 i = 0; i < lengthof(_original_objects); i++) { + _object_specs[i] = _original_objects[i]; _object_specs[i].grf_prop.local_id = i; } diff --git a/src/newgrf_object.h b/src/newgrf_object.h index f283e36407..df6958074e 100644 --- a/src/newgrf_object.h +++ b/src/newgrf_object.h @@ -99,6 +99,7 @@ struct ObjectSpec { bool IsAvailable() const; uint Index() const; + static size_t Count(); static const ObjectSpec *Get(ObjectType index); static const ObjectSpec *GetByTile(TileIndex tile); diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index 5f37b6d1c7..ce423273f4 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -207,7 +207,7 @@ CommandCost CmdBuildObject(DoCommandFlag flags, TileIndex tile, ObjectType type, { CommandCost cost(EXPENSES_CONSTRUCTION); - if (type >= NUM_OBJECTS) return CMD_ERROR; + if (type >= ObjectSpec::Count()) return CMD_ERROR; const ObjectSpec *spec = ObjectSpec::Get(type); if (_game_mode == GM_NORMAL && !spec->IsAvailable() && !_generating_world) return CMD_ERROR; if ((_game_mode == GM_EDITOR || _generating_world) && !spec->WasEverAvailable()) return CMD_ERROR; @@ -388,7 +388,7 @@ CommandCost CmdBuildObjectArea(DoCommandFlag flags, TileIndex tile, TileIndex st { if (start_tile >= Map::Size()) return CMD_ERROR; - if (type >= NUM_OBJECTS) return CMD_ERROR; + if (type >= ObjectSpec::Count()) return CMD_ERROR; const ObjectSpec *spec = ObjectSpec::Get(type); if (view >= spec->views) return CMD_ERROR; @@ -792,7 +792,7 @@ static bool TryBuildTransmitter() void GenerateObjects() { /* Set a guestimate on how much we progress */ - SetGeneratingWorldProgress(GWP_OBJECT, NUM_OBJECTS); + SetGeneratingWorldProgress(GWP_OBJECT, (uint)ObjectSpec::Count()); /* Determine number of water tiles at map border needed for freeform_edges */ uint num_water_tiles = 0; @@ -808,7 +808,7 @@ void GenerateObjects() } /* Iterate over all possible object types */ - for (uint i = 0; i < NUM_OBJECTS; i++) { + for (uint i = 0; i < ObjectSpec::Count(); i++) { const ObjectSpec *spec = ObjectSpec::Get(i); /* Continue, if the object was never available till now or shall not be placed */ diff --git a/src/object_gui.cpp b/src/object_gui.cpp index 7fb8e93c6f..b617115d1e 100644 --- a/src/object_gui.cpp +++ b/src/object_gui.cpp @@ -275,11 +275,11 @@ public: uint height[2] = {0, 0}; // The height for the different views; in this case views 1/2 and 4. /* Get the height and view information. */ - for (int i = 0; i < NUM_OBJECTS; i++) { + for (int i = 0; i < ObjectSpec::Count(); i++) { const ObjectSpec *spec = ObjectSpec::Get(i); if (!spec->IsEverAvailable()) continue; two_wide |= spec->views >= 2; - height[spec->views / 4] = std::max(ObjectSpec::Get(i)->height, height[spec->views / 4]); + height[spec->views / 4] = std::max(spec->height, height[spec->views / 4]); } /* Determine the pixel heights. */ diff --git a/src/script/api/script_objecttype.cpp b/src/script/api/script_objecttype.cpp index 7d74d9b8b8..842bdac4b7 100644 --- a/src/script/api/script_objecttype.cpp +++ b/src/script/api/script_objecttype.cpp @@ -19,7 +19,7 @@ /* static */ bool ScriptObjectType::IsValidObjectType(ObjectType object_type) { - if (object_type >= NUM_OBJECTS) return false; + if (object_type >= ObjectSpec::Count()) return false; return ObjectSpec::Get(object_type)->IsEverAvailable(); } diff --git a/src/script/api/script_objecttypelist.cpp b/src/script/api/script_objecttypelist.cpp index 0086260b20..0bb52b0576 100644 --- a/src/script/api/script_objecttypelist.cpp +++ b/src/script/api/script_objecttypelist.cpp @@ -15,7 +15,7 @@ ScriptObjectTypeList::ScriptObjectTypeList() { - for (int i = 0; i < NUM_OBJECTS; i++) { + for (int i = 0; i < ObjectSpec::Count(); i++) { const ObjectSpec *spec = ObjectSpec::Get(i); if (!spec->IsEverAvailable()) continue; this->AddItem(i); From 82c70ed3b85d453a77185eef094480392efc7694 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 15 Jan 2023 00:04:53 +0000 Subject: [PATCH 13/13] Change: Expose ObjectSpec vector to simplify iteration. --- src/newgrf_object.cpp | 5 +++++ src/newgrf_object.h | 1 + src/object_cmd.cpp | 17 ++++++++--------- src/object_gui.cpp | 9 ++++----- src/script/api/script_objecttypelist.cpp | 7 +++---- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp index a14f8d19ae..36910a3d26 100644 --- a/src/newgrf_object.cpp +++ b/src/newgrf_object.cpp @@ -31,6 +31,11 @@ extern const ObjectSpec _original_objects[NEW_OBJECT_OFFSET]; /** All the object specifications. */ std::vector _object_specs; +const std::vector &ObjectSpec::Specs() +{ + return _object_specs; +} + size_t ObjectSpec::Count() { return _object_specs.size(); diff --git a/src/newgrf_object.h b/src/newgrf_object.h index df6958074e..f23c1b0d9f 100644 --- a/src/newgrf_object.h +++ b/src/newgrf_object.h @@ -99,6 +99,7 @@ struct ObjectSpec { bool IsAvailable() const; uint Index() const; + static const std::vector &Specs(); static size_t Count(); static const ObjectSpec *Get(ObjectType index); static const ObjectSpec *GetByTile(TileIndex tile); diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index ce423273f4..3c80955fbb 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -808,21 +808,20 @@ void GenerateObjects() } /* Iterate over all possible object types */ - for (uint i = 0; i < ObjectSpec::Count(); i++) { - const ObjectSpec *spec = ObjectSpec::Get(i); + for (const auto &spec : ObjectSpec::Specs()) { /* Continue, if the object was never available till now or shall not be placed */ - if (!spec->WasEverAvailable() || spec->generate_amount == 0) continue; + if (!spec.WasEverAvailable() || spec.generate_amount == 0) continue; - uint16 amount = spec->generate_amount; + uint16 amount = spec.generate_amount; /* Scale by map size */ - if ((spec->flags & OBJECT_FLAG_SCALE_BY_WATER) && _settings_game.construction.freeform_edges) { + if ((spec.flags & OBJECT_FLAG_SCALE_BY_WATER) && _settings_game.construction.freeform_edges) { /* Scale the amount of lighthouses with the amount of land at the borders. * The -6 is because the top borders are MP_VOID (-2) and all corners * are counted twice (-4). */ amount = Map::ScaleBySize1D(amount * num_water_tiles) / (2 * Map::MaxY() + 2 * Map::MaxX() - 6); - } else if (spec->flags & OBJECT_FLAG_SCALE_BY_WATER) { + } else if (spec.flags & OBJECT_FLAG_SCALE_BY_WATER) { amount = Map::ScaleBySize1D(amount); } else { amount = Map::ScaleBySize(amount); @@ -830,7 +829,7 @@ void GenerateObjects() /* Now try to place the requested amount of this object */ for (uint j = Map::ScaleBySize(1000); j != 0 && amount != 0 && Object::CanAllocateItem(); j--) { - switch (i) { + switch (spec.Index()) { case OBJECT_TRANSMITTER: if (TryBuildTransmitter()) amount--; break; @@ -840,8 +839,8 @@ void GenerateObjects() break; default: - uint8 view = RandomRange(spec->views); - if (CmdBuildObject(DC_EXEC | DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, RandomTile(), i, view).Succeeded()) amount--; + uint8 view = RandomRange(spec.views); + if (CmdBuildObject(DC_EXEC | DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, RandomTile(), spec.Index(), view).Succeeded()) amount--; break; } } diff --git a/src/object_gui.cpp b/src/object_gui.cpp index b617115d1e..ea80d72d8a 100644 --- a/src/object_gui.cpp +++ b/src/object_gui.cpp @@ -275,11 +275,10 @@ public: uint height[2] = {0, 0}; // The height for the different views; in this case views 1/2 and 4. /* Get the height and view information. */ - for (int i = 0; i < ObjectSpec::Count(); i++) { - const ObjectSpec *spec = ObjectSpec::Get(i); - if (!spec->IsEverAvailable()) continue; - two_wide |= spec->views >= 2; - height[spec->views / 4] = std::max(spec->height, height[spec->views / 4]); + for (const auto &spec : ObjectSpec::Specs()) { + if (!spec.IsEverAvailable()) continue; + two_wide |= spec.views >= 2; + height[spec.views / 4] = std::max(spec.height, height[spec.views / 4]); } /* Determine the pixel heights. */ diff --git a/src/script/api/script_objecttypelist.cpp b/src/script/api/script_objecttypelist.cpp index 0bb52b0576..725997067b 100644 --- a/src/script/api/script_objecttypelist.cpp +++ b/src/script/api/script_objecttypelist.cpp @@ -15,9 +15,8 @@ ScriptObjectTypeList::ScriptObjectTypeList() { - for (int i = 0; i < ObjectSpec::Count(); i++) { - const ObjectSpec *spec = ObjectSpec::Get(i); - if (!spec->IsEverAvailable()) continue; - this->AddItem(i); + for (const auto &spec : ObjectSpec::Specs()) { + if (!spec.IsEverAvailable()) continue; + this->AddItem(spec.Index()); } }