mirror of https://github.com/OpenTTD/OpenTTD
Compare commits
5 Commits
390ddf2668
...
83d232232b
Author | SHA1 | Date |
---|---|---|
|
83d232232b | |
|
7c8759552a | |
|
8031d68d01 | |
|
7df9426000 | |
|
0b44deedd0 |
|
@ -110,7 +110,7 @@ struct Aircraft final : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
|
|||
uint Crash(bool flooded = false) override;
|
||||
TileIndex GetOrderStationLocation(StationID station) override;
|
||||
TileIndex GetCargoTile() const override { return this->First()->tile; }
|
||||
ClosestDepot FindClosestDepot() override;
|
||||
ClosestDepot FindClosestDepot(bool may_reverse = false) override;
|
||||
|
||||
/**
|
||||
* Check if the aircraft type is a normal flying device; eg
|
||||
|
|
|
@ -393,7 +393,7 @@ CommandCost CmdBuildAircraft(DoCommandFlags flags, TileIndex tile, const Engine
|
|||
}
|
||||
|
||||
|
||||
ClosestDepot Aircraft::FindClosestDepot()
|
||||
ClosestDepot Aircraft::FindClosestDepot([[maybe_unused]] bool may_reverse)
|
||||
{
|
||||
const Station *st = GetTargetAirportIfValid(this);
|
||||
/* If the station is not a valid airport or if it has no hangars */
|
||||
|
|
|
@ -697,8 +697,11 @@ STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL :{BLACK}Ne mutas
|
|||
STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO :{BLACK}Adott rakomány grafikonjának mutatása be/ki
|
||||
STR_GRAPH_CARGO_PAYMENT_CARGO :{TINY_FONT}{BLACK}{STRING}
|
||||
|
||||
STR_GRAPH_INDUSTRY_CAPTION :{WHITE}{INDUSTRY} - Rakománytörténet
|
||||
STR_GRAPH_INDUSTRY_RANGE_PRODUCED :Előállított
|
||||
STR_GRAPH_INDUSTRY_RANGE_TRANSPORTED :Szállítva
|
||||
STR_GRAPH_INDUSTRY_RANGE_DELIVERED :Leszállítva
|
||||
STR_GRAPH_INDUSTRY_RANGE_WAITING :Várakozik
|
||||
|
||||
STR_GRAPH_PERFORMANCE_DETAIL_TOOLTIP :{BLACK}Részletes teljesítményértékelés mutatása
|
||||
|
||||
|
@ -4087,6 +4090,8 @@ STR_INDUSTRY_VIEW_PRODUCTION_LAST_MONTH_TITLE :{BLACK}Múlt ha
|
|||
STR_INDUSTRY_VIEW_PRODUCTION_LAST_MINUTE_TITLE :{BLACK}Termelés az elmúlt percben:
|
||||
STR_INDUSTRY_VIEW_TRANSPORTED :{YELLOW}{CARGO_LONG}{STRING}{BLACK} ({COMMA}% elszállítva)
|
||||
STR_INDUSTRY_VIEW_LOCATION_TOOLTIP :{BLACK}A fő nézetet a gazdasági épületre állítja. Ctrl+kattintással új nézet nyílik a gazdasági épület helyzeténél
|
||||
STR_INDUSTRY_VIEW_CARGO_GRAPH :{BLACK}Rakomány grafikon
|
||||
STR_INDUSTRY_VIEW_CARGO_GRAPH_TOOLTIP :{BLACK}Megmutatja az iparág rakománytörténetének grafikonját
|
||||
STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}Termelési szint: {YELLOW}{COMMA}%
|
||||
STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}A gyár bejelentette a közelgő bezárását!
|
||||
|
||||
|
@ -5062,6 +5067,7 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}Sima tal
|
|||
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Rossz irányba lejt a föld
|
||||
STR_ERROR_CAN_T_DO_THIS :{WHITE}Nem teheted ezt...
|
||||
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Előbb le kell rombolnod az épületet
|
||||
STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}... a(z) épület védett
|
||||
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Nem tisztíthatod meg ezt a területet...
|
||||
STR_ERROR_SITE_UNSUITABLE :{WHITE}... nem alkalmas rá a hely
|
||||
STR_ERROR_ALREADY_BUILT :{WHITE}... már van itt
|
||||
|
|
|
@ -437,6 +437,7 @@ STR_SETTINGS_MENU_NEWGRF_SETTINGS :NewGRFの設定
|
|||
STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS :透過表示設定
|
||||
STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED :街名を表示
|
||||
STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED :駅名を表示
|
||||
STR_SETTINGS_MENU_STATION_NAMES_BUS :バス停
|
||||
STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED :中継駅名を表示
|
||||
STR_SETTINGS_MENU_SIGNS_DISPLAYED :標識を表示
|
||||
STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS :競争者の標識と名前を表示
|
||||
|
@ -522,6 +523,7 @@ STR_ABOUT_MENU_ABOUT_OPENTTD :OpenTTDにつ
|
|||
STR_ABOUT_MENU_SPRITE_ALIGNER :スプライトを整列
|
||||
STR_ABOUT_MENU_TOGGLE_BOUNDING_BOXES :バウンディングボックスの表示切替
|
||||
STR_ABOUT_MENU_TOGGLE_DIRTY_BLOCKS :ダーティーブロックの色付け切替
|
||||
STR_ABOUT_MENU_TOGGLE_WIDGET_OUTLINES :ウィジェットの枠線の表示切替
|
||||
|
||||
###length 31
|
||||
STR_DAY_NUMBER_1ST :1
|
||||
|
@ -1203,12 +1205,14 @@ STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER :中央
|
|||
STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT :右
|
||||
|
||||
|
||||
STR_CONFIG_SETTING_INFINITE_MONEY :無限の資金: {STRING}
|
||||
STR_CONFIG_SETTING_INFINITE_MONEY_HELPTEXT :無制限の支出を許容し、会社の破産も無効にします
|
||||
|
||||
STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN :初期の借入最大額: {STRING}
|
||||
STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN_HELPTEXT :初期の借入限度額を設定します (インフレは考慮されません)
|
||||
STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN_HELPTEXT :初期の借入限度額を設定します (インフレは考慮されません)。「借入金なし」に設定した場合、ゲームスクリプトか「無限の資金」オプションによる提供がない限り、資金は利用できなくなります。
|
||||
STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN_VALUE :{CURRENCY_LONG}
|
||||
###setting-zero-is-special
|
||||
STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN_DISABLED :借入金なし {RED}ゲームスクリプトで資金を受給する必要があります
|
||||
STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN_DISABLED :借入金なし
|
||||
|
||||
STR_CONFIG_SETTING_INTEREST_RATE :金利: {STRING}
|
||||
STR_CONFIG_SETTING_INTEREST_RATE_HELPTEXT :借入利率を設定します (インフレ設定を有効にしたときのインフレ率にも影響します)
|
||||
|
@ -1247,7 +1251,7 @@ STR_CONFIG_SETTING_TRAIN_REVERSING_HELPTEXT :設定を有効
|
|||
STR_CONFIG_SETTING_DISASTERS :災害: {STRING}
|
||||
STR_CONFIG_SETTING_DISASTERS_HELPTEXT :設定を有効にすると時折、乗り物や交通インフラを遮断・破壊する災害が起きるようになります
|
||||
|
||||
STR_CONFIG_SETTING_CITY_APPROVAL :議会の姿勢: {STRING}
|
||||
STR_CONFIG_SETTING_CITY_APPROVAL :地方自治体の姿勢: {STRING}
|
||||
STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :会社が街で引き起こした騒音(主に空港)や環境破壊がどの程度、街での評価や更なる建設行為に影響するかを設定します
|
||||
|
||||
STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT :マップ高さ限界: {STRING}
|
||||
|
@ -1351,10 +1355,10 @@ STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT_FULLSCREEN :する (フル
|
|||
STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT :する
|
||||
STR_CONFIG_SETTING_AUTOSCROLL_EVERY_VIEWPORT :する (ビューポートでも有効)
|
||||
|
||||
STR_CONFIG_SETTING_BRIBE :議会の買収: {STRING}
|
||||
STR_CONFIG_SETTING_BRIBE :地方自治体の贈賄: {STRING}
|
||||
###length 2
|
||||
STR_CONFIG_SETTING_BRIBE_HELPTEXT :街で議会買収を企てられるようになります。成功すれば街での評判が良くなりますが、地元当局に事が発覚した場合罰金を受けた上評判が悪くなり、その上その街では半年間何もできなくなります
|
||||
STR_CONFIG_SETTING_BRIBE_HELPTEXT_MINUTES :会社が議会買収を企てられるようにします。もし当局に事が発覚した場合、買収した会社は当該自治体では半年間何もできなくなります
|
||||
STR_CONFIG_SETTING_BRIBE_HELPTEXT :地方自治体への贈賄を企てられるようにします。もし当局に事が発覚した場合、贈賄を試みた会社は当該自治体では半年間何もできなくなります
|
||||
STR_CONFIG_SETTING_BRIBE_HELPTEXT_MINUTES :地方自治体への贈賄を企てられるようにします。もし当局に事が発覚した場合、贈賄を試みた会社は当該自治体では半年間何もできなくなります
|
||||
|
||||
STR_CONFIG_SETTING_ALLOW_EXCLUSIVE :独占運送契約の締結: {STRING}
|
||||
###length 2
|
||||
|
@ -1424,6 +1428,7 @@ STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES_HELPTEXT :有効にする
|
|||
|
||||
###setting-zero-is-special
|
||||
|
||||
STR_CONFIG_SETTING_CARGO_SCALE_VALUE :{NUM}%
|
||||
|
||||
STR_CONFIG_SETTING_AUTORENEW_VEHICLE :老朽車両の自動交換: {STRING}
|
||||
STR_CONFIG_SETTING_AUTORENEW_VEHICLE_HELPTEXT :有効にすると、耐用年数を越えた輸送機器は自動で更新されるようになります(交換には一度格納施設に戻る必要があります)。具体的な交換時期は下の設定で変更できます。
|
||||
|
@ -1858,7 +1863,7 @@ STR_CONFIG_SETTING_ALLOW_TOWN_ROADS_HELPTEXT :街の自治体
|
|||
STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS :街路との平面交差を許可: {STRING}
|
||||
STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT :有効にすると、会社が作る道路と街路とが交差できるようになります
|
||||
|
||||
STR_CONFIG_SETTING_NOISE_LEVEL :空港建設に対する街の騒音レベル規制: {STRING}
|
||||
STR_CONFIG_SETTING_NOISE_LEVEL :騒音レベルに基づいた空港建設の制限: {STRING}
|
||||
STR_CONFIG_SETTING_NOISE_LEVEL_HELPTEXT :この設定を無効にすると、街に作れる空港は最大2つまでになります。有効にした場合は、各空港の騒音レベルの総和が街の騒音許容レベル以下になるようにしか建てられません。騒音レベルは空港の大きさ・街からの距離により、騒音許容レベルは街の人口により左右されます
|
||||
|
||||
STR_CONFIG_SETTING_TOWN_FOUNDING :ゲーム中での街新設: {STRING}
|
||||
|
@ -1936,9 +1941,9 @@ STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER :初期の都市
|
|||
STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :ゲーム開始時に都市が普通の街に比べて平均して何倍の人口規模になるかを設定します
|
||||
|
||||
STR_CONFIG_SETTING_LINKGRAPH_RECALC_INTERVAL :行先分配グラフを{STRING}秒毎に更新
|
||||
STR_CONFIG_SETTING_LINKGRAPH_RECALC_INTERVAL_HELPTEXT :行先分配グラフの更新の間の待ち時間。各更新はグラフの一部だけのルートを再計算します。即ち、この設定を〇〇秒に指定する場合、全グラフが〇〇秒毎に更新されるのではありません。間隔が短ければ短いほどCPU時間を消費します。長ければ長いほど貨物流通の新規ルートの行先分配に時間がかかります。
|
||||
STR_CONFIG_SETTING_LINKGRAPH_RECALC_INTERVAL_HELPTEXT :行先分配グラフの再計算間隔。各計算タイミングでは一部のグラフのみが再計算されます。よって、ここ設定した X 秒ごとにグラフ全体が更新されるというわけではありません。再計算の間隔が短ければ短いほどCPU時間を消費します。長ければ長いほど貨物流通の新規ルートの行先分配に時間がかかります。
|
||||
STR_CONFIG_SETTING_LINKGRAPH_RECALC_TIME :行先分配の更新に{STRING}秒を割り当て
|
||||
STR_CONFIG_SETTING_LINKGRAPH_RECALC_TIME_HELPTEXT :行先分配グラフの更新に割り当てられる時間。更新が始まると、スレッドが生成されて、指定の時間に実行させられます。短ければ短いほど間に合わない可能性が高まります。その場合、ゲームは停止して計算完了を待ちます。長ければ長いほどルート変更の際に行先分配の更新に時間がかかります。
|
||||
STR_CONFIG_SETTING_LINKGRAPH_RECALC_TIME_HELPTEXT :行先分配グラフの再計算に割り当てられる時間。再計算が始まると、グラフの処理のために指定した生存秒数だけ実行可能なスレッドが作られます。生存秒数が短ければ短いほど再計算が間に合わない可能性が高まります。その際、ゲームは一時停止して計算完了を待ちます。生存秒数が長ければ長いほど、ルート変更の際に行先分配の更新に時間がかかります。
|
||||
|
||||
STR_CONFIG_SETTING_DISTRIBUTION_PAX :旅客の行先分配法: {STRING}
|
||||
STR_CONFIG_SETTING_DISTRIBUTION_PAX_HELPTEXT :旅客がどのように行き先別に分配されるかを設定します。「対称」ではAからBへ向かう乗客とほぼ同数が、BからAに向かうようになります。 「非対称」ではそれぞれの方向に向かう旅客数は独立に決められます。「無効」では行き先別分配をしなくなります。
|
||||
|
@ -1954,7 +1959,7 @@ STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC :非対称
|
|||
STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC :対称
|
||||
|
||||
STR_CONFIG_SETTING_LINKGRAPH_ACCURACY :分配精度: {STRING}
|
||||
STR_CONFIG_SETTING_LINKGRAPH_ACCURACY_HELPTEXT :この値を高くすると、リンクグラフ演算の為CPUへの負荷が大きくなります。演算に時間がかかりすぎると、目に見えてタイムラグが起こる場合があります。しかし低い値に設定すると、分配が不正確になり、望まれる場所に貨物が送られなくなる場合があります
|
||||
STR_CONFIG_SETTING_LINKGRAPH_ACCURACY_HELPTEXT :この設定値を高く設定すればするほど、行先分配グラフの計算に要するCPU時間が長くなります。計算に時間がかかりすぎると遅延が発生する可能性があります。一方、設定値を低く設定すると分配が不正確になり、荷物が意図された場所に送られない場合があります。
|
||||
|
||||
STR_CONFIG_SETTING_DEMAND_DISTANCE :距離効果: {STRING}
|
||||
STR_CONFIG_SETTING_DEMAND_DISTANCE_HELPTEXT :0より大きい値に設定すると、ある貨物の生産先Aと受取可能先Bとの距離がAからBへ送られる貨物量に影響を及ぼすようになります。高い値を設定すればするほど、遠い施設に送られる貨物量は少なくなり、近場の施設に送られる量が大きくなります
|
||||
|
@ -2058,8 +2063,10 @@ STR_CONFIG_ERROR_INVALID_BASE_MUSIC_NOT_FOUND :{WHITE}ファ
|
|||
# Video initalization errors
|
||||
STR_VIDEO_DRIVER_ERROR :{WHITE}ビデオ設定にエラーがあります...
|
||||
STR_VIDEO_DRIVER_ERROR_NO_HARDWARE_ACCELERATION :{WHITE}... 対応する GPU が見つかりません。ハードウェアアクセラレーションは無効になります。
|
||||
STR_VIDEO_DRIVER_ERROR_HARDWARE_ACCELERATION_CRASH :{WHITE}... GPUドライバーがゲームをクラッシュさせました。ハードウェアアクセラレーションは無効になりました
|
||||
|
||||
# Intro window
|
||||
STR_INTRO_CAPTION :{WHITE}OpenTTD
|
||||
|
||||
STR_INTRO_NEW_GAME :{BLACK}新しいゲーム
|
||||
STR_INTRO_LOAD_GAME :{BLACK}ロード
|
||||
|
@ -2070,6 +2077,7 @@ STR_INTRO_MULTIPLAYER :{BLACK}マル
|
|||
|
||||
STR_INTRO_GAME_OPTIONS :{BLACK}基本設定
|
||||
STR_INTRO_HIGHSCORE :{BLACK}ハイスコア
|
||||
STR_INTRO_HELP :{BLACK}ヘルプとマニュアル
|
||||
STR_INTRO_ONLINE_CONTENT :{BLACK}オンラインコンテンツの確認
|
||||
STR_INTRO_QUIT :{BLACK}終了
|
||||
|
||||
|
@ -2121,14 +2129,14 @@ STR_HELP_WINDOW_COMMUNITY :{BLACK}コミ
|
|||
STR_CHEATS :{WHITE}サンドボックスのオプション
|
||||
STR_CHEAT_MONEY :{LTBLUE}預金残高を{CURRENCY_LONG}増やす
|
||||
STR_CHEAT_CHANGE_COMPANY :{LTBLUE}会社: {ORANGE}{COMMA}を乗っ取ってプレイする
|
||||
STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}魔法のブルドーザー(産業拠点等、何でも撤去できる): {ORANGE}{STRING}
|
||||
STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}魔法のブルドーザー(産業拠点など何でも撤去可能): {ORANGE}{STRING}
|
||||
STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}トンネルの平面交差を許容: {ORANGE}{STRING}
|
||||
STR_CHEAT_NO_JETCRASH :{LTBLUE}ジェット機の小型空港での墜落率を減少: {ORANGE}{STRING}
|
||||
STR_CHEAT_EDIT_MAX_HL :{LTBLUE}マップの最高高度を変更: {ORANGE}{NUM}
|
||||
STR_CHEAT_EDIT_MAX_HL_QUERY_CAPT :{WHITE}マップの最大高度
|
||||
STR_CHEAT_CHANGE_DATE :{LTBLUE}日付を変更: {ORANGE}{DATE_SHORT}
|
||||
STR_CHEAT_CHANGE_DATE_QUERY_CAPT :{WHITE}現在日時を変更
|
||||
STR_CHEAT_SETUP_PROD :{LTBLUE}生産量変更: {ORANGE}{STRING}
|
||||
STR_CHEAT_SETUP_PROD :{LTBLUE}産業の生産量の変更を有効化: {ORANGE}{STRING}
|
||||
|
||||
# Livery window
|
||||
STR_LIVERY_CAPTION :{WHITE}{COMPANY} - 配色
|
||||
|
@ -2457,6 +2465,7 @@ STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :リンクグラ
|
|||
STR_NETWORK_MESSAGE_CLIENT_LEAVING :退出
|
||||
STR_NETWORK_MESSAGE_CLIENT_JOINED :*** {STRING} が参加してきました
|
||||
STR_NETWORK_MESSAGE_CLIENT_JOINED_ID :*** {STRING} がゲームに参加してきました (クライアント #{NUM})
|
||||
STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {0:STRING} が{STRING}の経営に参画してきました
|
||||
STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} がゲームを観覧し始めました
|
||||
STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} が新会社 (#{NUM}) を設立しました
|
||||
STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} が退出しました({STRING})
|
||||
|
@ -2672,6 +2681,7 @@ STR_SELECT_ROAD_BRIDGE_CAPTION :{WHITE}道路
|
|||
STR_SELECT_BRIDGE_SELECTION_TOOLTIP :{BLACK}建設したい橋の種類をクリックしてください
|
||||
STR_SELECT_BRIDGE_INFO_NAME :{GOLD}{STRING}
|
||||
STR_SELECT_BRIDGE_INFO_NAME_MAX_SPEED :{GOLD}{STRING}{} {VELOCITY}
|
||||
STR_SELECT_BRIDGE_INFO_NAME_COST :{GOLD}{STRING}{} {WHITE}{CURRENCY_LONG}
|
||||
STR_SELECT_BRIDGE_INFO_NAME_MAX_SPEED_COST :{GOLD}{STRING}{} {VELOCITY} {WHITE}{CURRENCY_LONG}
|
||||
STR_BRIDGE_NAME_SUSPENSION_STEEL :吊橋(S造)
|
||||
STR_BRIDGE_NAME_GIRDER_STEEL :桁橋(S造)
|
||||
|
@ -3458,7 +3468,7 @@ STR_LOCAL_AUTHORITY_ACTION_ROAD_RECONSTRUCTION :道路補修に
|
|||
STR_LOCAL_AUTHORITY_ACTION_STATUE_OF_COMPANY :社長の彫像を建設
|
||||
STR_LOCAL_AUTHORITY_ACTION_NEW_BUILDINGS :市街地開発に出資
|
||||
STR_LOCAL_AUTHORITY_ACTION_EXCLUSIVE_TRANSPORT :独占運送契約を締結
|
||||
STR_LOCAL_AUTHORITY_ACTION_BRIBE :議会を買収
|
||||
STR_LOCAL_AUTHORITY_ACTION_BRIBE :地方自治体への贈賄
|
||||
###next-name-looks-similar
|
||||
|
||||
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{PUSH_COLOUR}{YELLOW}旅客と貨物を確保する為に、街で新聞広告を実施します。{}より多くの旅客と貨物が自社の交通網を利用するようになります。{}{POP_COLOUR}費用: {CURRENCY_LONG}
|
||||
|
@ -3466,7 +3476,7 @@ STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{PUSH_COLOUR}{Y
|
|||
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{PUSH_COLOUR}{YELLOW}旅客と貨物を確保する為に、街でTV-CMを開始します{}街の中心部の大範囲にある駅の評価が一時的に高まります。{}{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_BRIBE :{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} 目標
|
||||
|
@ -4374,6 +4384,7 @@ STR_ORDER_REFIT_STOP_ORDER :({STRING}に改
|
|||
STR_ORDER_STOP_ORDER :(運用停止)
|
||||
|
||||
|
||||
STR_ORDER_GO_TO_STATION :{STRING} {STATION}
|
||||
STR_ORDER_GO_TO_STATION_CAN_T_USE_STATION :{PUSH_COLOUR}{RED}(駅を使用できません){POP_COLOUR} {STRING} {STATION}
|
||||
|
||||
STR_ORDER_IMPLICIT :(自動)
|
||||
|
@ -4432,6 +4443,7 @@ STR_TIMETABLE_TOOLTIP :{BLACK}ダイ
|
|||
STR_TIMETABLE_NO_TRAVEL :運行計画無
|
||||
STR_TIMETABLE_NOT_TIMETABLEABLE :該当区間を運行 (次の手動指令により自動設定)
|
||||
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :該当区間を運行 (ダイヤ設定無)
|
||||
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED :最高速度{VELOCITY}で該当区間を運行 (ダイヤ設定無)
|
||||
STR_TIMETABLE_TRAVEL_FOR :{STRING}で該当区間を運行
|
||||
STR_TIMETABLE_TRAVEL_FOR_SPEED :{STRING}で該当区間を運行(最高速度{VELOCITY})
|
||||
STR_TIMETABLE_TRAVEL_FOR_ESTIMATED :運行({0:STRING}・ダイヤ設定無)
|
||||
|
@ -4525,14 +4537,14 @@ STR_AI_CONFIG_MOVE_DOWN :{BLACK}下に
|
|||
STR_AI_CONFIG_MOVE_DOWN_TOOLTIP :{BLACK}選択したAIの順位を下げる
|
||||
|
||||
STR_AI_CONFIG_GAMESCRIPT :{SILVER}ゲームスクリプト
|
||||
STR_AI_CONFIG_GAMESCRIPT_PARAM :{SILVER}パラメータ
|
||||
STR_AI_CONFIG_GAMESCRIPT_PARAM :{SILVER}パラメーター
|
||||
STR_AI_CONFIG_AI :{SILVER}AI
|
||||
|
||||
STR_AI_CONFIG_CHANGE_AI :{BLACK}AIを選択
|
||||
STR_AI_CONFIG_CHANGE_GAMESCRIPT :{BLACK}ゲームスクリプトを選択
|
||||
STR_AI_CONFIG_CHANGE_TOOLTIP :{BLACK}他のスクリプトをロードします。Ctrl+クリックで全ての利用可能バージョンを表示します
|
||||
STR_AI_CONFIG_CONFIGURE :{BLACK}設定
|
||||
STR_AI_CONFIG_CONFIGURE_TOOLTIP :{BLACK}スクリプトのパラメータを設定します
|
||||
STR_AI_CONFIG_CONFIGURE_TOOLTIP :{BLACK}スクリプトのパラメーターを設定します
|
||||
|
||||
# Available AIs window
|
||||
STR_AI_LIST_CAPTION :{WHITE}使用可能な{STRING}
|
||||
|
@ -4556,8 +4568,8 @@ STR_SCREENSHOT_HEIGHTMAP_SCREENSHOT :{BLACK}ハイ
|
|||
STR_SCREENSHOT_MINIMAP_SCREENSHOT :{BLACK}ミニマップのスクリーンショット
|
||||
|
||||
# Script Parameters
|
||||
STR_AI_SETTINGS_CAPTION_AI :AI
|
||||
STR_AI_SETTINGS_CAPTION_GAMESCRIPT :ゲームスクリプト
|
||||
STR_AI_SETTINGS_CAPTION_AI :{WHITE}AIのパラメーター
|
||||
STR_AI_SETTINGS_CAPTION_GAMESCRIPT :{WHITE}ゲームスクリプトのパラメーター
|
||||
STR_AI_SETTINGS_RESET :{BLACK}リセット
|
||||
STR_AI_SETTINGS_SETTING :{STRING}: {ORANGE}{STRING}
|
||||
|
||||
|
@ -4638,6 +4650,7 @@ STR_ERROR_SCREENSHOT_FAILED :{WHITE}スク
|
|||
|
||||
# Error message titles
|
||||
STR_ERROR_MESSAGE_CAPTION :{YELLOW}メッセージ
|
||||
STR_ERROR_MESSAGE_CAPTION_OTHER_COMPANY :{YELLOW}{COMPANY}からのメッセージ
|
||||
|
||||
# Generic construction errors
|
||||
STR_ERROR_OFF_EDGE_OF_MAP :{WHITE}マップからはみ出します
|
||||
|
@ -4656,12 +4669,13 @@ STR_ERROR_TERRAFORM_LIMIT_REACHED :{WHITE}一度
|
|||
STR_ERROR_CLEARING_LIMIT_REACHED :{WHITE}一度にできる撤去量を越えています
|
||||
STR_ERROR_TREE_PLANT_LIMIT_REACHED :{WHITE}木の本数が多すぎます
|
||||
STR_ERROR_NAME_MUST_BE_UNIQUE :{WHITE}名前は重複してはいけません
|
||||
STR_ERROR_GENERIC_OBJECT_IN_THE_WAY :{WHITE}{STRING}があります
|
||||
STR_ERROR_NOT_ALLOWED_WHILE_PAUSED :{WHITE}ポーズ中にはできない行動です
|
||||
|
||||
# Local authority errors
|
||||
STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS :{WHITE}{TOWN}議会が反対しています
|
||||
STR_ERROR_LOCAL_AUTHORITY_REFUSES_AIRPORT :{WHITE}{TOWN}議会はこれ以上の空港建設を認可しない方針です
|
||||
STR_ERROR_LOCAL_AUTHORITY_REFUSES_NOISE :{WHITE}{TOWN}の地元民が騒音公害を理由に空港建設に反対しています
|
||||
STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS :{WHITE}{TOWN}の地方自治体が反対しています
|
||||
STR_ERROR_LOCAL_AUTHORITY_REFUSES_AIRPORT :{WHITE}{TOWN}の地方自治体はこれ以上の空港建設を許可しません
|
||||
STR_ERROR_LOCAL_AUTHORITY_REFUSES_NOISE :{WHITE}{TOWN}の地方自治体は騒音公害の懸念から空港建設を許可しません
|
||||
STR_ERROR_BRIBE_FAILED :{WHITE}あなたの行った贈収賄が地元当局に露見しました!
|
||||
|
||||
# Levelling errors
|
||||
|
@ -5535,3 +5549,8 @@ STR_SHIP :{BLACK}{SHIP}
|
|||
|
||||
STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY})
|
||||
|
||||
STR_BADGE_CONFIG_MENU_TOOLTIP :バッジ設定を開く
|
||||
STR_BADGE_CONFIG_RESET :リセット
|
||||
STR_BADGE_CONFIG_ICONS :{WHITE}バッジのアイコン
|
||||
STR_BADGE_CONFIG_FILTERS :{WHITE}バッジのフィルター
|
||||
STR_BADGE_CONFIG_NAME :名前
|
||||
|
|
|
@ -1896,10 +1896,11 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v)
|
|||
* Update the vehicle's destination tile from an order.
|
||||
* @param order the order the vehicle currently has
|
||||
* @param v the vehicle to update
|
||||
* @param may_reverse Whether the vehicle is allowed to reverse when executing the updated order.
|
||||
* @param conditional_depth the depth (amount of steps) to go with conditional orders. This to prevent infinite loops.
|
||||
* @param pbs_look_ahead Whether we are forecasting orders for pbs reservations in advance. If true, the order indices must not be modified.
|
||||
*/
|
||||
bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool pbs_look_ahead)
|
||||
bool UpdateOrderDest(Vehicle *v, const Order *order, bool may_reverse, int conditional_depth, bool pbs_look_ahead)
|
||||
{
|
||||
if (conditional_depth > v->GetNumOrders()) {
|
||||
v->current_order.Free();
|
||||
|
@ -1926,7 +1927,7 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
|
|||
if (v->dest_tile == 0 && TimerGameEconomy::date_fract != (v->index % Ticks::DAY_TICKS)) break;
|
||||
|
||||
/* We need to search for the nearest depot (hangar). */
|
||||
ClosestDepot closest_depot = v->FindClosestDepot();
|
||||
ClosestDepot closest_depot = v->FindClosestDepot(may_reverse);
|
||||
|
||||
if (closest_depot.found) {
|
||||
/* PBS reservations cannot reverse */
|
||||
|
@ -2018,7 +2019,7 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
|
|||
}
|
||||
|
||||
v->current_order = *order;
|
||||
return UpdateOrderDest(v, order, conditional_depth + 1, pbs_look_ahead);
|
||||
return UpdateOrderDest(v, order, may_reverse, conditional_depth + 1, pbs_look_ahead);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2116,7 +2117,7 @@ bool ProcessOrders(Vehicle *v)
|
|||
break;
|
||||
}
|
||||
|
||||
return UpdateOrderDest(v, order) && may_reverse;
|
||||
return UpdateOrderDest(v, order, may_reverse) && may_reverse;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,7 +20,7 @@ void InvalidateVehicleOrder(const Vehicle *v, int data);
|
|||
void CheckOrders(const Vehicle*);
|
||||
void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist = false, bool reset_order_indices = true);
|
||||
bool ProcessOrders(Vehicle *v);
|
||||
bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth = 0, bool pbs_look_ahead = false);
|
||||
bool UpdateOrderDest(Vehicle *v, const Order *order, bool may_reverse = false, int conditional_depth = 0, bool pbs_look_ahead = false);
|
||||
VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v);
|
||||
uint GetOrderDistance(VehicleOrderID prev, VehicleOrderID cur, const Vehicle *v, int conditional_depth = 0);
|
||||
|
||||
|
|
|
@ -430,3 +430,83 @@ void PrintWaterRegionDebugInfo(TileIndex tile)
|
|||
{
|
||||
GetUpdatedWaterRegion(tile).PrintDebugInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the provided callback function on all tiles of the water patch of the region
|
||||
* and returns true on the first tile that passes the callback test.
|
||||
* @param callback The test function that will be called for the water patch.
|
||||
* @param water_region_patch Water patch within the water region to test the callback.
|
||||
* @return true if it passes the callback test, or false if the callback failed.
|
||||
*/
|
||||
bool TestTileInWaterRegionPatch(const WaterRegionPatchDesc &water_region_patch, TestTileIndexCallBack &callback)
|
||||
{
|
||||
const WaterRegion region = GetUpdatedWaterRegion(water_region_patch.x, water_region_patch.y);
|
||||
|
||||
/* Check if the region has a tile which passes the callback test. */
|
||||
for (const TileIndex tile : region) {
|
||||
if (region.GetLabel(tile) != water_region_patch.label || !callback(tile)) continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the provided callback function on all tiles of the current water patch of the region, collects the
|
||||
* tiles which passed the callback and returns the tile closest to the edge from where the region is entered from.
|
||||
* @param high_level_path A span containing at least current and parent water patches.
|
||||
* @param callback The test function that will be called for each tile in the water patch.
|
||||
* @return The tile closest to the edge from where it came from that passed the callback test, or INVALID_TILE if no tile passed.
|
||||
*/
|
||||
TileIndex FindClosestEnteringTile(const std::span<WaterRegionPatchDesc> high_level_path, TestTileIndexCallBack &callback)
|
||||
{
|
||||
assert(high_level_path.size() > 1);
|
||||
|
||||
const WaterRegionPatchDesc ¤t_water_region_patch = high_level_path.back();
|
||||
const WaterRegion current_region = GetUpdatedWaterRegion(current_water_region_patch.x, current_water_region_patch.y);
|
||||
|
||||
/* Check if the current region has a tile which passes the callback test. */
|
||||
std::vector<TileIndex> tile_list;
|
||||
for (const TileIndex tile : current_region) {
|
||||
if (current_region.GetLabel(tile) != current_water_region_patch.label || !callback(tile)) continue;
|
||||
|
||||
/* We collect the tiles when we know which region we came from for further evaluation. */
|
||||
tile_list.push_back(tile);
|
||||
}
|
||||
|
||||
/* If there aren't any tiles that passed the callback, return with an invalid tile. */
|
||||
if (tile_list.empty()) return INVALID_TILE;
|
||||
|
||||
/* If there's only one, just return it. */
|
||||
if (tile_list.size() == 1) return tile_list.front();
|
||||
|
||||
const TileIndex top_tile = current_region.begin();
|
||||
const TileIndex bot_tile = TileAddXY(top_tile, WATER_REGION_EDGE_LENGTH - 1, WATER_REGION_EDGE_LENGTH - 1);
|
||||
|
||||
/* Get the side from which the current region is entered from. */
|
||||
const WaterRegionPatchDesc &parent_water_region_patch = high_level_path[high_level_path.size() - 2];
|
||||
const WaterRegion parent_region = GetUpdatedWaterRegion(parent_water_region_patch.x, parent_water_region_patch.y);
|
||||
const DiagDirection side = DiagdirBetweenTiles(top_tile, parent_region.begin());
|
||||
|
||||
/* Depending on the side, determine which corner tile to use to extract their x or y coordinates. */
|
||||
const bool is_at_top = side == DIAGDIR_NE || side == DIAGDIR_NW;
|
||||
const TileIndex edge_tile = is_at_top ? top_tile : bot_tile;
|
||||
const bool is_axis_x = DiagDirToAxis(side) == AXIS_X;
|
||||
const int x_or_y_edge = is_axis_x ? TileX(edge_tile) : TileY(edge_tile);
|
||||
|
||||
/* With more than one tile passing the callback, calculate the tile that is closest to the edge from whence it came. */
|
||||
TileIndex best_tile = INVALID_TILE;
|
||||
int best_dist = WATER_REGION_EDGE_LENGTH;
|
||||
for (const TileIndex &tile : tile_list) {
|
||||
const int x_or_y_tile = is_axis_x ? TileX(tile) : TileY(tile);
|
||||
const int dist_to_edge = std::abs(x_or_y_tile - x_or_y_edge);
|
||||
assert(dist_to_edge < WATER_REGION_EDGE_LENGTH);
|
||||
if (dist_to_edge >= best_dist) continue;
|
||||
|
||||
best_dist = dist_to_edge;
|
||||
best_tile = tile;
|
||||
}
|
||||
|
||||
return best_tile;
|
||||
}
|
||||
|
|
|
@ -64,4 +64,8 @@ void AllocateWaterRegions();
|
|||
|
||||
void PrintWaterRegionDebugInfo(TileIndex tile);
|
||||
|
||||
using TestTileIndexCallBack = std::function<bool(const TileIndex)>;
|
||||
bool TestTileInWaterRegionPatch(const WaterRegionPatchDesc &water_region_patch, TestTileIndexCallBack &callback);
|
||||
TileIndex FindClosestEnteringTile(const std::span<WaterRegionPatchDesc> high_level_path, TestTileIndexCallBack &callback);
|
||||
|
||||
#endif /* WATER_REGIONS_H */
|
||||
|
|
|
@ -34,6 +34,17 @@ Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipP
|
|||
*/
|
||||
bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir);
|
||||
|
||||
/**
|
||||
* Used when user sends ship to the nearest depot or if ship needs servicing using YAPF.
|
||||
* @param v ship that needs to go to some depot
|
||||
* @param max_penalty max distance (in pathfinder penalty) from the current ship position
|
||||
* (used also as optimization - the pathfinder can stop path finding if max_penalty
|
||||
* was reached and no depot was seen)
|
||||
* @param may_reverse whether the ship is allowed to reverse
|
||||
* @return the data about the depot
|
||||
*/
|
||||
FindDepotData YapfShipFindNearestDepot(const Ship *v, int max_penalty, bool may_reverse);
|
||||
|
||||
/**
|
||||
* Finds the best path for given road vehicle using YAPF.
|
||||
* @param v the RV that needs to find a path
|
||||
|
|
|
@ -36,6 +36,7 @@ protected:
|
|||
TileIndex dest_tile;
|
||||
TrackdirBits dest_trackdirs;
|
||||
StationID dest_station;
|
||||
bool any_ship_depot = false;
|
||||
|
||||
bool has_intermediate_dest = false;
|
||||
TileIndex intermediate_dest_tile;
|
||||
|
@ -55,6 +56,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void SetAnyShipDepotDestination()
|
||||
{
|
||||
this->any_ship_depot = true;
|
||||
}
|
||||
|
||||
void SetIntermediateDestination(const WaterRegionPatchDesc &water_region_patch)
|
||||
{
|
||||
this->has_intermediate_dest = true;
|
||||
|
@ -69,10 +75,16 @@ protected:
|
|||
return *static_cast<Tpf*>(this);
|
||||
}
|
||||
|
||||
TestTileIndexCallBack detect_ship_depot = [&](const TileIndex tile)
|
||||
{
|
||||
return IsShipDepotTile(tile) && GetShipDepotPart(tile) == DEPOT_PART_NORTH && IsTileOwner(tile, Yapf().GetVehicle()->owner);
|
||||
};
|
||||
|
||||
public:
|
||||
/** Called by YAPF to detect if node ends in the desired destination. */
|
||||
inline bool PfDetectDestination(Node &n)
|
||||
{
|
||||
if (this->any_ship_depot) return this->detect_ship_depot(n.key.tile);
|
||||
return this->PfDetectDestinationTile(n.segment_last_tile, n.segment_last_td);
|
||||
}
|
||||
|
||||
|
@ -89,6 +101,11 @@ public:
|
|||
return tile == this->dest_tile && ((this->dest_trackdirs & TrackdirToTrackdirBits(trackdir)) != TRACKDIR_BIT_NONE);
|
||||
}
|
||||
|
||||
inline TileIndex GetShipDepotDestination(const std::span<WaterRegionPatchDesc> high_level_path)
|
||||
{
|
||||
return FindClosestEnteringTile(high_level_path, this->detect_ship_depot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by YAPF to calculate cost estimate. Calculates distance to the destination
|
||||
* adds it to the actual cost from origin and stores the sum to the Node::estimate.
|
||||
|
@ -99,7 +116,7 @@ public:
|
|||
|
||||
static const int dg_dir_to_x_offs[] = { -1, 0, 1, 0 };
|
||||
static const int dg_dir_to_y_offs[] = { 0, 1, 0, -1 };
|
||||
if (this->PfDetectDestination(n)) {
|
||||
if (this->any_ship_depot || this->PfDetectDestination(n)) {
|
||||
n.estimate = n.cost;
|
||||
return true;
|
||||
}
|
||||
|
@ -158,7 +175,7 @@ public:
|
|||
}
|
||||
|
||||
/** Restricts the search by creating corridor or water regions through which the ship is allowed to travel. */
|
||||
inline void RestrictSearch(const std::vector<WaterRegionPatchDesc> &path)
|
||||
inline void RestrictSearch(const std::span<WaterRegionPatchDesc> &path)
|
||||
{
|
||||
this->water_region_corridor.clear();
|
||||
for (const WaterRegionPatchDesc &path_entry : path) this->water_region_corridor.push_back(path_entry);
|
||||
|
@ -211,16 +228,20 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
static Trackdir ChooseShipTrack(const Ship *v, TileIndex tile, TrackdirBits forward_dirs, TrackdirBits reverse_dirs,
|
||||
static Trackdir ChooseShipTrack(const Ship *v, TileIndex &tile, TrackdirBits forward_dirs, TrackdirBits reverse_dirs, int max_penalty,
|
||||
bool &path_found, ShipPathCache &path_cache, Trackdir &best_origin_dir)
|
||||
{
|
||||
const std::vector<WaterRegionPatchDesc> high_level_path = YapfShipFindWaterRegionPath(v, tile, NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1);
|
||||
std::vector<WaterRegionPatchDesc> high_level_path = YapfShipFindWaterRegionPath(v, tile, NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1);
|
||||
if (high_level_path.empty()) {
|
||||
path_found = false;
|
||||
/* Make the ship move around aimlessly. This prevents repeated pathfinder calls and clearly indicates that the ship is lost. */
|
||||
return CreateRandomPath(v, path_cache, SHIP_LOST_PATH_LENGTH);
|
||||
}
|
||||
|
||||
const bool find_closest_depot = tile == INVALID_TILE;
|
||||
if (find_closest_depot) tile = v->tile;
|
||||
const bool automatic_servicing = find_closest_depot && max_penalty != 0;
|
||||
|
||||
/* Try one time without restricting the search area, which generally results in better and more natural looking paths.
|
||||
* However the pathfinder can hit the node limit in certain situations such as long aqueducts or maze-like terrain.
|
||||
* If that happens we run the pathfinder again, but restricted only to the regions provided by the region pathfinder. */
|
||||
|
@ -229,13 +250,28 @@ public:
|
|||
|
||||
/* Set origin and destination nodes */
|
||||
pf.SetOrigin(v->tile, forward_dirs | reverse_dirs);
|
||||
pf.SetDestination(v);
|
||||
const bool is_intermediate_destination = static_cast<int>(high_level_path.size()) >= NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1;
|
||||
if (is_intermediate_destination) pf.SetIntermediateDestination(high_level_path.back());
|
||||
if (find_closest_depot) {
|
||||
pf.SetAnyShipDepotDestination();
|
||||
} else {
|
||||
pf.SetDestination(v);
|
||||
}
|
||||
pf.SetMaxCost(max_penalty);
|
||||
|
||||
const std::span<WaterRegionPatchDesc> high_level_path_span(high_level_path.data(), std::min<size_t>(high_level_path.size(), NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1));
|
||||
const bool is_intermediate_destination = static_cast<int>(high_level_path_span.size()) >= NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1;
|
||||
if (is_intermediate_destination) {
|
||||
if (automatic_servicing) {
|
||||
/* Automatic servicing requires a valid path cost from start to end.
|
||||
* However, when an intermediate destination is set, the resulting cost
|
||||
* cannot be used to determine if it falls within the maximum allowed penalty. */
|
||||
return INVALID_TRACKDIR;
|
||||
}
|
||||
pf.SetIntermediateDestination(high_level_path_span.back());
|
||||
}
|
||||
|
||||
/* Restrict the search area to prevent the low level pathfinder from expanding too many nodes. This can happen
|
||||
* when the terrain is very "maze-like" or when the high level path "teleports" via a very long aqueduct. */
|
||||
if (attempt > 0) pf.RestrictSearch(high_level_path);
|
||||
if (attempt > 0) pf.RestrictSearch(high_level_path_span);
|
||||
|
||||
/* Find best path. */
|
||||
path_found = pf.FindPath(v);
|
||||
|
@ -245,6 +281,12 @@ public:
|
|||
/* Make the ship move around aimlessly. This prevents repeated pathfinder calls and clearly indicates that the ship is lost. */
|
||||
if (!path_found) return CreateRandomPath(v, path_cache, SHIP_LOST_PATH_LENGTH);
|
||||
|
||||
/* Return early when only searching for the closest depot tile. */
|
||||
if (find_closest_depot) {
|
||||
tile = is_intermediate_destination ? pf.GetShipDepotDestination(high_level_path) : node->GetTile();
|
||||
return INVALID_TRACKDIR;
|
||||
}
|
||||
|
||||
/* Return only the path within the current water region if an intermediate destination was returned. If not, cache the entire path
|
||||
* to the final destination tile. The low-level pathfinder might actually prefer a different docking tile in a nearby region. Without
|
||||
* caching the full path the ship can get stuck in a loop. */
|
||||
|
@ -254,7 +296,7 @@ public:
|
|||
while (node->parent) {
|
||||
const WaterRegionPatchDesc node_water_patch = GetWaterRegionPatchInfo(node->GetTile());
|
||||
|
||||
const bool node_water_patch_on_high_level_path = std::ranges::find(high_level_path, node_water_patch) != high_level_path.end();
|
||||
const bool node_water_patch_on_high_level_path = std::ranges::find(high_level_path_span, node_water_patch) != high_level_path_span.end();
|
||||
const bool add_full_path = !is_intermediate_destination && node_water_patch != end_water_patch;
|
||||
|
||||
/* The cached path must always lead to a region patch that's on the high level path.
|
||||
|
@ -303,6 +345,7 @@ public:
|
|||
{
|
||||
bool path_found = false;
|
||||
ShipPathCache dummy_cache;
|
||||
TileIndex tile = v->tile;
|
||||
Trackdir best_origin_dir = INVALID_TRACKDIR;
|
||||
|
||||
if (trackdir == nullptr) {
|
||||
|
@ -310,17 +353,45 @@ public:
|
|||
const Trackdir reverse_dir = ReverseTrackdir(v->GetVehicleTrackdir());
|
||||
const TrackdirBits forward_dirs = TrackdirToTrackdirBits(v->GetVehicleTrackdir());
|
||||
const TrackdirBits reverse_dirs = TrackdirToTrackdirBits(reverse_dir);
|
||||
(void)ChooseShipTrack(v, v->tile, forward_dirs, reverse_dirs, path_found, dummy_cache, best_origin_dir);
|
||||
(void)ChooseShipTrack(v, tile, forward_dirs, reverse_dirs, 0, path_found, dummy_cache, best_origin_dir);
|
||||
return path_found && best_origin_dir == reverse_dir;
|
||||
} else {
|
||||
/* This gets called when a ship suddenly can't move forward, e.g. due to terraforming. */
|
||||
const DiagDirection entry = ReverseDiagDir(VehicleExitDir(v->direction, v->state));
|
||||
const TrackdirBits reverse_dirs = DiagdirReachesTrackdirs(entry) & TrackStatusToTrackdirBits(GetTileTrackStatus(v->tile, TRANSPORT_WATER, 0, entry));
|
||||
(void)ChooseShipTrack(v, v->tile, TRACKDIR_BIT_NONE, reverse_dirs, path_found, dummy_cache, best_origin_dir);
|
||||
(void)ChooseShipTrack(v, tile, TRACKDIR_BIT_NONE, reverse_dirs, 0, path_found, dummy_cache, best_origin_dir);
|
||||
*trackdir = path_found && best_origin_dir != INVALID_TRACKDIR ? best_origin_dir : GetRandomTrackdir(reverse_dirs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the best depot for a ship.
|
||||
* @param v Ship
|
||||
* @param max_penalty maximum pathfinder cost.
|
||||
* @param may_reverse whether the ship is allowed to reverse.
|
||||
* @return FindDepotData with the best depot tile, cost and whether to reverse.
|
||||
*/
|
||||
static inline FindDepotData FindNearestDepot(const Ship *v, int max_penalty, bool may_reverse)
|
||||
{
|
||||
FindDepotData depot;
|
||||
|
||||
bool path_found = false;
|
||||
ShipPathCache dummy_cache;
|
||||
TileIndex tile = INVALID_TILE;
|
||||
Trackdir best_origin_dir = INVALID_TRACKDIR;
|
||||
const bool search_both_ways = may_reverse && max_penalty == 0;
|
||||
const Trackdir forward_dir = v->GetVehicleTrackdir();
|
||||
const Trackdir reverse_dir = ReverseTrackdir(forward_dir);
|
||||
const TrackdirBits forward_dirs = TrackdirToTrackdirBits(forward_dir);
|
||||
const TrackdirBits reverse_dirs = search_both_ways ? TrackdirToTrackdirBits(reverse_dir) : TRACKDIR_BIT_NONE;
|
||||
(void)ChooseShipTrack(v, tile, forward_dirs, reverse_dirs, max_penalty, path_found, dummy_cache, best_origin_dir);
|
||||
if (path_found) {
|
||||
assert(tile != INVALID_TILE);
|
||||
depot.tile = tile;
|
||||
}
|
||||
return depot;
|
||||
}
|
||||
};
|
||||
|
||||
/** Cost Provider module of YAPF for ships. */
|
||||
|
@ -333,6 +404,11 @@ public:
|
|||
typedef typename Types::NodeList::Item Node; ///< this will be our node type.
|
||||
typedef typename Node::Key Key; ///< key to hash tables.
|
||||
|
||||
protected:
|
||||
int max_cost;
|
||||
|
||||
CYapfCostShipT() : max_cost(0) {}
|
||||
|
||||
/** to access inherited path finder */
|
||||
Tpf &Yapf()
|
||||
{
|
||||
|
@ -340,6 +416,11 @@ public:
|
|||
}
|
||||
|
||||
public:
|
||||
inline void SetMaxCost(int cost)
|
||||
{
|
||||
this->max_cost = cost;
|
||||
}
|
||||
|
||||
inline int CurveCost(Trackdir td1, Trackdir td2)
|
||||
{
|
||||
assert(IsValidTrackdir(td1));
|
||||
|
@ -384,6 +465,10 @@ public:
|
|||
uint8_t speed_frac = (GetEffectiveWaterClass(n.GetTile()) == WATER_CLASS_SEA) ? svi->ocean_speed_frac : svi->canal_speed_frac;
|
||||
if (speed_frac > 0) c += YAPF_TILE_LENGTH * (1 + tf->tiles_skipped) * speed_frac / (256 - speed_frac);
|
||||
|
||||
/* Finish if we already exceeded the maximum path cost (i.e. when
|
||||
* searching for the nearest depot). */
|
||||
if (this->max_cost > 0 && (n.parent->cost + c) > this->max_cost) return false;
|
||||
|
||||
/* Apply it. */
|
||||
n.cost = n.parent->cost + c;
|
||||
return true;
|
||||
|
@ -422,7 +507,7 @@ Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipP
|
|||
{
|
||||
Trackdir best_origin_dir = INVALID_TRACKDIR;
|
||||
const TrackdirBits origin_dirs = TrackdirToTrackdirBits(v->GetVehicleTrackdir());
|
||||
const Trackdir td_ret = CYapfShip::ChooseShipTrack(v, tile, origin_dirs, TRACKDIR_BIT_NONE, path_found, path_cache, best_origin_dir);
|
||||
const Trackdir td_ret = CYapfShip::ChooseShipTrack(v, tile, origin_dirs, TRACKDIR_BIT_NONE, 0, path_found, path_cache, best_origin_dir);
|
||||
return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK;
|
||||
}
|
||||
|
||||
|
@ -430,3 +515,8 @@ bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir)
|
|||
{
|
||||
return CYapfShip::CheckShipReverse(v, trackdir);
|
||||
}
|
||||
|
||||
FindDepotData YapfShipFindNearestDepot(const Ship *v, int max_penalty, bool may_reverse)
|
||||
{
|
||||
return CYapfShip::FindNearestDepot(v, max_penalty, may_reverse);
|
||||
}
|
||||
|
|
|
@ -119,6 +119,7 @@ public:
|
|||
|
||||
protected:
|
||||
Key dest;
|
||||
bool any_ship_depot = false;
|
||||
|
||||
public:
|
||||
void SetDestination(const WaterRegionPatchDesc &water_region_patch)
|
||||
|
@ -126,18 +127,32 @@ public:
|
|||
this->dest.Set(water_region_patch);
|
||||
}
|
||||
|
||||
void SetAnyShipDepotDestination()
|
||||
{
|
||||
this->any_ship_depot = true;
|
||||
}
|
||||
|
||||
protected:
|
||||
TestTileIndexCallBack detect_ship_depot = [&](const TileIndex tile)
|
||||
{
|
||||
return IsShipDepotTile(tile) && GetShipDepotPart(tile) == DEPOT_PART_NORTH && IsTileOwner(tile, Yapf().GetVehicle()->owner);
|
||||
};
|
||||
|
||||
Tpf &Yapf() { return *static_cast<Tpf*>(this); }
|
||||
|
||||
public:
|
||||
inline bool PfDetectDestination(Node &n) const
|
||||
inline bool PfDetectDestination(Node &n)
|
||||
{
|
||||
if (this->any_ship_depot) {
|
||||
return TestTileInWaterRegionPatch(n.key.water_region_patch, this->detect_ship_depot);
|
||||
}
|
||||
|
||||
return n.key == this->dest;
|
||||
}
|
||||
|
||||
inline bool PfCalcEstimate(Node &n)
|
||||
{
|
||||
if (this->PfDetectDestination(n)) {
|
||||
if (this->any_ship_depot || this->PfDetectDestination(n)) {
|
||||
n.estimate = n.cost;
|
||||
return true;
|
||||
}
|
||||
|
@ -218,6 +233,31 @@ public:
|
|||
assert(!path.empty());
|
||||
return path;
|
||||
}
|
||||
|
||||
static std::vector<WaterRegionPatchDesc> FindShipDepotRegionPath(const Ship *v)
|
||||
{
|
||||
const WaterRegionPatchDesc start_water_region_patch = GetWaterRegionPatchInfo(v->tile);
|
||||
|
||||
/* We reserve 4 nodes (patches) per water region. The vast majority of water regions have 1 or 2 regions so this should be a pretty
|
||||
* safe limit. We cap the limit at 65536 which is at a region size of 16x16 is equivalent to one node per region for a 4096x4096 map. */
|
||||
Tpf pf(std::min(static_cast<int>(Map::Size() * NODES_PER_REGION) / WATER_REGION_NUMBER_OF_TILES, MAX_NUMBER_OF_NODES));
|
||||
pf.AddOrigin(start_water_region_patch);
|
||||
pf.SetAnyShipDepotDestination();
|
||||
|
||||
/* Find best path. */
|
||||
if (!pf.FindPath(v)) return {}; // Path not found.
|
||||
|
||||
std::vector<WaterRegionPatchDesc> path;
|
||||
Node *node = pf.GetBestNode();
|
||||
while (node != nullptr) {
|
||||
path.push_back(node->key.water_region_patch);
|
||||
node = node->parent;
|
||||
}
|
||||
|
||||
assert(!path.empty());
|
||||
std::ranges::reverse(path);
|
||||
return path;
|
||||
}
|
||||
};
|
||||
|
||||
/** Cost Provider of YAPF for water regions. */
|
||||
|
@ -296,5 +336,8 @@ struct CYapfRegionWater : CYapfT<CYapfRegion_TypesT<CYapfRegionWater, CRegionNod
|
|||
*/
|
||||
std::vector<WaterRegionPatchDesc> YapfShipFindWaterRegionPath(const Ship *v, TileIndex start_tile, int max_returned_path_length)
|
||||
{
|
||||
const bool find_closest_depot = start_tile == INVALID_TILE;
|
||||
|
||||
if (find_closest_depot) return CYapfRegionWater::FindShipDepotRegionPath(v);
|
||||
return CYapfRegionWater::FindWaterRegionPath(v, start_tile, max_returned_path_length);
|
||||
}
|
||||
|
|
|
@ -16,5 +16,6 @@
|
|||
struct Ship;
|
||||
|
||||
std::vector<WaterRegionPatchDesc> YapfShipFindWaterRegionPath(const Ship *v, TileIndex start_tile, int max_returned_path_length);
|
||||
std::vector<WaterRegionPatchDesc> YapfFindShipDepotRegionPath(const Ship *v);
|
||||
|
||||
#endif /* YAPF_SHIP_REGIONS_H */
|
||||
|
|
|
@ -132,7 +132,7 @@ struct RoadVehicle final : public GroundVehicle<RoadVehicle, VEH_ROAD> {
|
|||
uint Crash(bool flooded = false) override;
|
||||
Trackdir GetVehicleTrackdir() const override;
|
||||
TileIndex GetOrderStationLocation(StationID station) override;
|
||||
ClosestDepot FindClosestDepot() override;
|
||||
ClosestDepot FindClosestDepot(bool may_reverse = false) override;
|
||||
|
||||
bool IsBus() const;
|
||||
|
||||
|
|
|
@ -346,7 +346,7 @@ static FindDepotData FindClosestRoadDepot(const RoadVehicle *v, int max_distance
|
|||
return YapfRoadVehicleFindNearestDepot(v, max_distance);
|
||||
}
|
||||
|
||||
ClosestDepot RoadVehicle::FindClosestDepot()
|
||||
ClosestDepot RoadVehicle::FindClosestDepot([[maybe_unused]] bool may_reverse)
|
||||
{
|
||||
FindDepotData rfdd = FindClosestRoadDepot(this, 0);
|
||||
if (rfdd.best_length == UINT_MAX) return ClosestDepot();
|
||||
|
|
|
@ -57,7 +57,7 @@ struct Ship final : public SpecializedVehicle<Ship, VEH_SHIP> {
|
|||
void OnNewEconomyDay() override;
|
||||
Trackdir GetVehicleTrackdir() const override;
|
||||
TileIndex GetOrderStationLocation(StationID station) override;
|
||||
ClosestDepot FindClosestDepot() override;
|
||||
ClosestDepot FindClosestDepot(bool may_reverse = false) override;
|
||||
void UpdateCache();
|
||||
void SetDestTile(TileIndex tile) override;
|
||||
};
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "station_base.h"
|
||||
#include "newgrf_engine.h"
|
||||
#include "pathfinder/yapf/yapf.h"
|
||||
#include "pathfinder/yapf/yapf_ship_regions.h"
|
||||
#include "newgrf_sound.h"
|
||||
#include "spritecache.h"
|
||||
#include "strings_func.h"
|
||||
|
@ -39,13 +38,8 @@
|
|||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
/** Max distance in tiles (as the crow flies) to search for depots when user clicks "go to depot". */
|
||||
constexpr int MAX_SHIP_DEPOT_SEARCH_DISTANCE = 80;
|
||||
|
||||
/**
|
||||
* Determine the effective #WaterClass for a ship travelling on a tile.
|
||||
* @param tile Tile of interest
|
||||
|
@ -148,57 +142,15 @@ void Ship::GetImage(Direction direction, EngineImageType image_type, VehicleSpri
|
|||
result->Set(_ship_sprites[spritenum] + direction);
|
||||
}
|
||||
|
||||
static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance)
|
||||
static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance, bool may_reverse = false)
|
||||
{
|
||||
const int max_region_distance = (max_distance / WATER_REGION_EDGE_LENGTH) + 1;
|
||||
const TileIndex tile = v->tile;
|
||||
if (IsShipDepotTile(tile) && IsTileOwner(tile, v->owner)) return Depot::GetByTile(tile);
|
||||
|
||||
static std::unordered_set<int> visited_patch_hashes;
|
||||
static std::deque<WaterRegionPatchDesc> patches_to_search;
|
||||
visited_patch_hashes.clear();
|
||||
patches_to_search.clear();
|
||||
FindDepotData sfdd = YapfShipFindNearestDepot(Ship::From(v), max_distance, may_reverse);
|
||||
|
||||
/* Step 1: find a set of reachable Water Region Patches using BFS. */
|
||||
const WaterRegionPatchDesc start_patch = GetWaterRegionPatchInfo(v->tile);
|
||||
patches_to_search.push_back(start_patch);
|
||||
visited_patch_hashes.insert(CalculateWaterRegionPatchHash(start_patch));
|
||||
|
||||
while (!patches_to_search.empty()) {
|
||||
/* Remove first patch from the queue and make it the current patch. */
|
||||
const WaterRegionPatchDesc current_node = patches_to_search.front();
|
||||
patches_to_search.pop_front();
|
||||
|
||||
/* Add neighbours of the current patch to the search queue. */
|
||||
VisitWaterRegionPatchCallback visit_func = [&](const WaterRegionPatchDesc &water_region_patch) {
|
||||
/* Note that we check the max distance per axis, not the total distance. */
|
||||
if (std::abs(water_region_patch.x - start_patch.x) > max_region_distance ||
|
||||
std::abs(water_region_patch.y - start_patch.y) > max_region_distance) return;
|
||||
|
||||
const int hash = CalculateWaterRegionPatchHash(water_region_patch);
|
||||
if (visited_patch_hashes.count(hash) == 0) {
|
||||
visited_patch_hashes.insert(hash);
|
||||
patches_to_search.push_back(water_region_patch);
|
||||
}
|
||||
};
|
||||
|
||||
VisitWaterRegionPatchNeighbours(current_node, visit_func);
|
||||
}
|
||||
|
||||
/* Step 2: Find the closest depot within the reachable Water Region Patches. */
|
||||
const Depot *best_depot = nullptr;
|
||||
uint best_dist_sq = std::numeric_limits<uint>::max();
|
||||
for (const Depot *depot : Depot::Iterate()) {
|
||||
const TileIndex tile = depot->xy;
|
||||
if (IsShipDepotTile(tile) && IsTileOwner(tile, v->owner)) {
|
||||
const uint dist_sq = DistanceSquare(tile, v->tile);
|
||||
if (dist_sq < best_dist_sq && dist_sq <= max_distance * max_distance &&
|
||||
visited_patch_hashes.count(CalculateWaterRegionPatchHash(GetWaterRegionPatchInfo(tile))) > 0) {
|
||||
best_dist_sq = dist_sq;
|
||||
best_depot = depot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return best_depot;
|
||||
if (sfdd.tile == INVALID_TILE) return nullptr;
|
||||
return Depot::GetByTile(sfdd.tile);
|
||||
}
|
||||
|
||||
static void CheckIfShipNeedsService(Vehicle *v)
|
||||
|
@ -209,7 +161,7 @@ static void CheckIfShipNeedsService(Vehicle *v)
|
|||
return;
|
||||
}
|
||||
|
||||
uint max_distance = _settings_game.pf.yapf.maximum_go_to_depot_penalty / YAPF_TILE_LENGTH;
|
||||
uint max_distance = _settings_game.pf.yapf.maximum_go_to_depot_penalty;
|
||||
|
||||
const Depot *depot = FindClosestShipDepot(v, max_distance);
|
||||
|
||||
|
@ -948,9 +900,9 @@ CommandCost CmdBuildShip(DoCommandFlags flags, TileIndex tile, const Engine *e,
|
|||
return CommandCost();
|
||||
}
|
||||
|
||||
ClosestDepot Ship::FindClosestDepot()
|
||||
ClosestDepot Ship::FindClosestDepot(bool may_reverse)
|
||||
{
|
||||
const Depot *depot = FindClosestShipDepot(this, MAX_SHIP_DEPOT_SEARCH_DISTANCE);
|
||||
const Depot *depot = FindClosestShipDepot(this, 0, may_reverse);
|
||||
if (depot == nullptr) return ClosestDepot();
|
||||
|
||||
return ClosestDepot(depot->xy, depot->index);
|
||||
|
|
|
@ -129,7 +129,7 @@ struct Train final : public GroundVehicle<Train, VEH_TRAIN> {
|
|||
uint Crash(bool flooded = false) override;
|
||||
Trackdir GetVehicleTrackdir() const override;
|
||||
TileIndex GetOrderStationLocation(StationID station) override;
|
||||
ClosestDepot FindClosestDepot() override;
|
||||
ClosestDepot FindClosestDepot(bool may_reverse = false) override;
|
||||
|
||||
void ReserveTrackUnderConsist() const;
|
||||
|
||||
|
|
|
@ -2185,7 +2185,7 @@ static FindDepotData FindClosestTrainDepot(Train *v, int max_distance)
|
|||
return YapfTrainFindNearestDepot(v, max_distance);
|
||||
}
|
||||
|
||||
ClosestDepot Train::FindClosestDepot()
|
||||
ClosestDepot Train::FindClosestDepot([[maybe_unused]] bool may_reverse)
|
||||
{
|
||||
FindDepotData tfdd = FindClosestTrainDepot(this, 0);
|
||||
if (tfdd.best_length == UINT_MAX) return ClosestDepot();
|
||||
|
|
|
@ -2594,7 +2594,7 @@ CommandCost Vehicle::SendToDepot(DoCommandFlags flags, DepotCommandFlags command
|
|||
return CommandCost();
|
||||
}
|
||||
|
||||
ClosestDepot closest_depot = this->FindClosestDepot();
|
||||
ClosestDepot closest_depot = this->FindClosestDepot(true);
|
||||
static const StringID no_depot[] = {STR_ERROR_UNABLE_TO_FIND_ROUTE_TO, STR_ERROR_UNABLE_TO_FIND_LOCAL_DEPOT, STR_ERROR_UNABLE_TO_FIND_LOCAL_DEPOT, STR_ERROR_CAN_T_SEND_AIRCRAFT_TO_HANGAR};
|
||||
if (!closest_depot.found) return CommandCost(no_depot[this->type]);
|
||||
|
||||
|
|
|
@ -787,9 +787,10 @@ public:
|
|||
/**
|
||||
* Find the closest depot for this vehicle and tell us the location,
|
||||
* DestinationID and whether we should reverse.
|
||||
* @param may_reverse Whether the vehicle is allowed to reverse.
|
||||
* @return A structure with information about the closest depot, if found.
|
||||
*/
|
||||
virtual ClosestDepot FindClosestDepot() { return {}; }
|
||||
virtual ClosestDepot FindClosestDepot([[maybe_unused]] bool may_reverse = false) { return {}; }
|
||||
|
||||
virtual void SetDestTile(TileIndex tile) { this->dest_tile = tile; }
|
||||
|
||||
|
|
Loading…
Reference in New Issue