1
0
Fork 0

Compare commits

...

3 Commits

Author SHA1 Message Date
Peter Nelson fe06bfe544
Merge 67bb5fc5c5 into ae917cb8c6 2025-07-23 04:50:29 +00:00
translators ae917cb8c6 Update: Translations from eints
vietnamese: 134 changes by MagicalDrizzle
2025-07-23 04:48:20 +00:00
Peter Nelson 67bb5fc5c5
Change: Merge town view and local authority windows. 2025-07-19 23:53:47 +01:00
8 changed files with 433 additions and 375 deletions

View File

@ -3691,10 +3691,15 @@ STR_TOWN_VIEW_TOWN_GROWS_EVERY_FUNDED :{BLACK}Town gro
STR_TOWN_VIEW_TOWN_GROW_STOPPED :{BLACK}Town is {RED}not{BLACK} growing
STR_TOWN_VIEW_NOISE_IN_TOWN :{BLACK}Noise limit in town: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA}
STR_TOWN_VIEW_CENTER_TOOLTIP :{BLACK}Centre the main view on town location. Ctrl+Click to open a new viewport on town location
STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON :{BLACK}Local Authority
STR_TOWN_VIEW_LOCAL_AUTHORITY_TOOLTIP :{BLACK}Show information on local authority
STR_TOWN_VIEW_RENAME_TOOLTIP :{BLACK}Change town name
STR_TOWN_VIEW_INFO :Information
STR_TOWN_VIEW_INFO_TOOLTIP :Switch to town information tab
STR_TOWN_VIEW_RATINGS :Ratings
STR_TOWN_VIEW_RATINGS_TOOLTIP :Switch to local authority ratings tab
STR_TOWN_VIEW_ACTIONS :Actions
STR_TOWN_VIEW_ACTIONS_TOOLTIP :Switch to local authority actions tab
STR_TOWN_VIEW_EXPAND_BUTTON :{BLACK}Expand
STR_TOWN_VIEW_EXPAND_TOOLTIP :{BLACK}Increase size of town
STR_TOWN_VIEW_EXPAND_BUILDINGS_BUTTON :{BLACK}Expand buildings
@ -3706,8 +3711,6 @@ STR_TOWN_VIEW_DELETE_TOOLTIP :{BLACK}Delete t
STR_TOWN_VIEW_RENAME_TOWN_BUTTON :Rename Town
# Town local authority window
STR_LOCAL_AUTHORITY_CAPTION :{WHITE}{TOWN} local authority
STR_LOCAL_AUTHORITY_ZONE :{BLACK}Zone
STR_LOCAL_AUTHORITY_ZONE_TOOLTIP :{BLACK}Show zone within local authority boundaries
STR_LOCAL_AUTHORITY_COMPANY_RATINGS :{BLACK}Transport company ratings:

View File

@ -267,6 +267,7 @@ STR_UNITS_YEARS :{NUM}{NBSP}năm
STR_UNITS_PERIODS :{NUM}{NBSP}kỳ
STR_LIST_SEPARATOR :,{SPACE}
STR_TRUNCATION_ELLIPSIS :...
# Common window strings
STR_LIST_FILTER_TITLE :{BLACK}Lọc:
@ -285,7 +286,7 @@ STR_TOOLTIP_CLOSE_WINDOW :{BLACK}Đóng c
STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS :{BLACK}Tiêu đề cửa sổ - kéo nó để di chuyển cửa số
STR_TOOLTIP_SHADE :{BLACK}Thu gọn cửa sổ - Chỉ hiển thị thanh tiêu đề
STR_TOOLTIP_DEBUG :{BLACK}Hiện thông tin debug của NewGRF
STR_TOOLTIP_DEFSIZE :{BLACK}Chuyển cửa sổ về kích thước mặc định. Ctrl+Click để lưu kích thước hiện tại làm mặc định
STR_TOOLTIP_DEFSIZE :{BLACK}Chuyển cửa sổ về kích thước mặc định. Ctrl+Click để lưu kích thước hiện tại làm mặc định. Ctri+Click kép để thiết lập lại mặc định cũ.
STR_TOOLTIP_STICKY :{BLACK}Đánh dấu không-thể-đóng khi bấm nút "Đóng Tất Cả Cửa Sổ". Ctrl+Click để lưu thành trạng thái mặc định
STR_TOOLTIP_RESIZE :{BLACK}Click và kéo để thay đổi kích thước cửa sổ
STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Bật kích cỡ cửa sổ lớn/nhỏ
@ -451,6 +452,12 @@ STR_SETTINGS_MENU_SANDBOX_OPTIONS :Tuỳ chọn Sa
STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS :Thiết lập hiệu ứng trong suốt
STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED :Hiển thị tên thị trấn
STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED :Hiển thị tên nhà ga
STR_SETTINGS_MENU_STATION_NAMES_TRAIN :Ga tàu
STR_SETTINGS_MENU_STATION_NAMES_LORRY :Trạm xe tải
STR_SETTINGS_MENU_STATION_NAMES_BUS :Trạm xe buýt
STR_SETTINGS_MENU_STATION_NAMES_SHIP :Cảng
STR_SETTINGS_MENU_STATION_NAMES_PLANE :Sân bay
STR_SETTINGS_MENU_STATION_NAMES_GHOST :Trạm ma
STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED :Hiển thị tên điểm mốc
STR_SETTINGS_MENU_SIGNS_DISPLAYED :Hiển thị ký hiệu
STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS :Hiển thị biển hiệu và tên của đối thủ
@ -627,8 +634,11 @@ STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL :{BLACK}Không h
STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO :{BLACK}Bật/tắt đồ thị cho hàng hóa này
STR_GRAPH_CARGO_PAYMENT_CARGO :{TINY_FONT}{BLACK}{STRING}
STR_GRAPH_INDUSTRY_CAPTION :{WHITE}{INDUSTRY} - Lịch sử hàng hóa
STR_GRAPH_INDUSTRY_RANGE_PRODUCED :Đã cung cấp
STR_GRAPH_INDUSTRY_RANGE_TRANSPORTED :Đã vận chuyển
STR_GRAPH_INDUSTRY_RANGE_DELIVERED :Đã giao
STR_GRAPH_INDUSTRY_RANGE_WAITING :Đang chờ...
STR_GRAPH_PERFORMANCE_DETAIL_TOOLTIP :{BLACK}Hiện chi tiết đánh giá chỉ số năng suất
@ -958,11 +968,14 @@ STR_GAME_OPTIONS_TAB_SOUND :Âm thanh
STR_GAME_OPTIONS_TAB_SOUND_TOOLTIP :Lựa chọn thiết lập cho âm thanh và nhạc
STR_GAME_OPTIONS_TAB_SOCIAL :Xã hội
STR_GAME_OPTIONS_TAB_SOCIAL_TOOLTIP :Chọn thiết lập các tích hợp xã hội
STR_GAME_OPTIONS_TAB_ADVANCED :Tùy chọn nâng cao
STR_GAME_OPTIONS_TAB_ADVANCED_TOOLTIP :Thay đổi tùy chọn nâng cao
STR_GAME_OPTIONS_VOLUME :Âm lượng
STR_GAME_OPTIONS_SFX_VOLUME :Hiệu ứng âm thanh
STR_GAME_OPTIONS_MUSIC_VOLUME :Âm nhạc
STR_GAME_OPTIONS_SETTING :{STRING}: {ORANGE}{STRING}
STR_GAME_OPTIONS_VOLUME_MARK :{NUM}%
@ -1016,6 +1029,7 @@ STR_GAME_OPTIONS_CURRENCY_IDR :Rupiah Indonesi
STR_GAME_OPTIONS_CURRENCY_MYR :Ringgit Malaysia
STR_GAME_OPTIONS_CURRENCY_LVL :Lát-vi-a Lats
STR_GAME_OPTIONS_CURRENCY_PTE :Escudo Bồ Đào Nha
STR_GAME_OPTIONS_CURRENCY_UAH :Hryvnia Ukraina
STR_GAME_OPTIONS_AUTOSAVE_FRAME :Lưu tự động
STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP :Lựa chọn khoảng thời gian tự động lưu
@ -1049,6 +1063,7 @@ STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :Đánh dấu v
STR_GAME_OPTIONS_VIDEO_DRIVER_INFO :Trình điều khiển hiện tại: {STRING}
STR_GAME_OPTIONS_INTERFACE :Giao diện
STR_GAME_OPTIONS_GUI_SCALE_FRAME :Kích thước giao diện
STR_GAME_OPTIONS_GUI_SCALE_TOOLTIP :Kéo thanh trượt để điều chỉnh kích thước giao diện. Giữ Ctrl để điều chỉnh liên tục
@ -1073,6 +1088,7 @@ STR_GAME_OPTIONS_PARTICIPATE_SURVEY_LINK_TOOLTIP :Sẽ mở trìn
STR_GAME_OPTIONS_PARTICIPATE_SURVEY_PREVIEW :Xem trước kết quả khảo sát
STR_GAME_OPTIONS_PARTICIPATE_SURVEY_PREVIEW_TOOLTIP :Hiển thị kết quả khảo sát ở ván chơi hiện tại
STR_GAME_OPTIONS_DISPLAY :Hiển thị
STR_GAME_OPTIONS_REFRESH_RATE :Tần số quét màn hình
STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP :Chọn tần số quét màn hình
@ -1094,7 +1110,7 @@ STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP :Thông tin thê
STR_GAME_OPTIONS_ONLINE_CONTENT :Tải Nội Dung
STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP :Kiểm tra những nội dung mới & cập nhật để tải về
STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE :{LTBLUE}(không có plugins được cài đặt để tích hợp vào nền tảng xã hội)
STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE :(không có plugins được cài đặt để tích hợp vào nền tảng xã hội)
STR_GAME_OPTIONS_SOCIAL_PLUGIN_TITLE :{STRING} ({STRING})
STR_GAME_OPTIONS_SOCIAL_PLUGIN_PLATFORM :Nền tảng:
@ -1288,6 +1304,9 @@ STR_CONFIG_SETTING_INTEREST_RATE_HELPTEXT :Lãi xuất vay
STR_CONFIG_SETTING_RUNNING_COSTS :Chi phí hoạt động: {STRING}
STR_CONFIG_SETTING_RUNNING_COSTS_HELPTEXT :Thiết lập mức độ tính chi phí bảo trì và vận hành đối với phương tiện và hạ tầng giao thông
###length 3
STR_CONFIG_SETTING_RUNNING_COSTS_LOW :Thấp
STR_CONFIG_SETTING_RUNNING_COSTS_MEDIUM :Trung bình
STR_CONFIG_SETTING_RUNNING_COSTS_HIGH :Cao
STR_CONFIG_SETTING_CONSTRUCTION_SPEED :Tốc độ xây dựng: {STRING}
STR_CONFIG_SETTING_CONSTRUCTION_SPEED_HELPTEXT :Giới hạn hành động xây dựng của AI
@ -1310,6 +1329,9 @@ STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Không có tr
STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Chi phí xây dựng: {STRING}
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Thiết lập mức độ xây dựng và chi phí mua sắm
###length 3
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_LOW :Thấp
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_MEDIUM :Trung bình
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HIGH :Cao
STR_CONFIG_SETTING_RECESSIONS :Suy thoái: {STRING}
STR_CONFIG_SETTING_RECESSIONS_HELPTEXT :Nếu bật, thì các đợt suy thoái sẽ xảy ra vài năm một lần. Trong suy thoái tất cả sản xuất sẽ giảm mạnh (và sẽ trở lại như cũ sau khi suy thoái kết thúc)
@ -1979,8 +2001,12 @@ STR_CONFIG_SETTING_TOWN_FOUNDING_FORBIDDEN :không cho phé
STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED :cho phép
STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT :cho phép, tùy chọn bố trí đô thị
STR_CONFIG_SETTING_HOUSE_PLACER :Đật từng ngôi nhà: {STRING}
STR_CONFIG_SETTING_HOUSE_PLACER_HELPTEXT :Bật tùy chọn này cho phép người chơi đặt nhà cửa bằng tay
###length 3
STR_CONFIG_SETTING_HOUSE_PLACER_FORBIDDEN :Không cho phép
STR_CONFIG_SETTING_HOUSE_PLACER_ALLOWED :Cho phép
STR_CONFIG_SETTING_HOUSE_PLACER_FULLY_CONSTRUCTED :Cho phép, đã hoàn thành thi công
STR_CONFIG_SETTING_TOWN_CARGOGENMODE :Nhu cầu vận chuyển hàng đô thị: {STRING}
STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :Lượng hàng hoá cần vận chuyển ở trong đô thị, tỉ lệ với tổng dân số của độ thị.{}Tăng tỉ lệ bình phương: một đô thị to gấp 2 sẽ tăng 4 lần số hành khách.{}Tăng tỉ lệ thuận: một đô thị tăng gấp 2 sẽ tăng gấp 2 lần số hành khách
@ -2009,7 +2035,7 @@ STR_CONFIG_SETTING_SOFT_LIMIT :Giới hạn s
STR_CONFIG_SETTING_SOFT_LIMIT_HELPTEXT :Số lượng cửa sổ chưa neo (tối đa) trước khi tự động đóng để nhường chỗ khi mở cửa sổ mới
STR_CONFIG_SETTING_SOFT_LIMIT_VALUE :{COMMA}
###setting-zero-is-special
STR_CONFIG_SETTING_SOFT_LIMIT_DISABLED :tắt
STR_CONFIG_SETTING_SOFT_LIMIT_DISABLED :Tắt
STR_CONFIG_SETTING_ZOOM_MIN :Độ phóng to tối đa: {STRING}
STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT :Độ phóng to tối đa của cửa sổ. Độ càng cao thì yêu cầu bộ nhớ càng nhiều
@ -2061,9 +2087,9 @@ STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :Loại hàng h
STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT :Chế độ phân phối đối với các loại hàng hóa mặc định: {STRING}
STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT :"Không đối xứng" có nghĩa là số lượng hàng hóa tùy ý có thể được gửi theo một trong hai hướng. "Thủ công" có nghĩa là những loại hàng hóa đó sẽ không được phân phối tự động
###length 3
STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :bằng tay
STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC :bất đối xứng
STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC :đối xứng
STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :Bằng tay
STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC :Bất đối xứng
STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC :Đối xứng
STR_CONFIG_SETTING_LINKGRAPH_ACCURACY :Độ chính xác phân phối: {STRING}
STR_CONFIG_SETTING_LINKGRAPH_ACCURACY_HELPTEXT :Mức chính xác tính toán đồ thị, nếu giá trị càng cao càng tốn CPU và trò chơi có thể chậm phản ứng, tuy nhiên giá trị thấp sẽ khiến việc phân phối sẽ giảm sự chính xác và bạn sẽ thấy sự khác biệt là hàng hóa không gửi đến chỗ cần đến
@ -2124,7 +2150,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m)
STR_CONFIG_SETTING_LOCALISATION :Tiêu Chuẩn Đo Lường
STR_CONFIG_SETTING_GRAPHICS :Đồ họa
STR_CONFIG_SETTING_SOUND :Âm thanh
STR_CONFIG_SETTING_INTERFACE :Giao Diện
STR_CONFIG_SETTING_INTERFACE :Giao diện
STR_CONFIG_SETTING_INTERFACE_GENERAL :Tổng quát
STR_CONFIG_SETTING_INTERFACE_VIEWPORTS :Vùng nhìn
STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION :Xây Dựng
@ -2178,6 +2204,8 @@ STR_VIDEO_DRIVER_ERROR_NO_HARDWARE_ACCELERATION :{WHITE}... khô
STR_VIDEO_DRIVER_ERROR_HARDWARE_ACCELERATION_CRASH :{WHITE}... trình điều khiển GPU đã làm trò chơi bị lỗi. Tăng tốc phần cứng đã được tắt
# Intro window
STR_INTRO_CAPTION :{WHITE}OpenTTD
STR_INTRO_VERSION :OpenTTD {REV}
STR_INTRO_NEW_GAME :{BLACK}Màn Chơi Mới
STR_INTRO_LOAD_GAME :{BLACK}Nạp Ván Chơi
@ -2311,16 +2339,19 @@ STR_FACE_SIMPLE_TOOLTIP :{BLACK}Trình c
STR_FACE_LOAD :{BLACK}Nạp
STR_FACE_LOAD_TOOLTIP :{BLACK}Chọn vẻ mặt ưa thích
STR_FACE_LOAD_DONE :{WHITE}Vẻ mặt ưa thích đã được nạp từ file thiết lập của OpenTTD.
STR_FACE_FACECODE :{BLACK}Khuôn mặt thứ.
STR_FACE_FACECODE_TOOLTIP :{BLACK}Xem và/hoặc sửa số vẻ mặt của chủ tịch công ty
STR_FACE_FACECODE_CAPTION :{WHITE}Xem và/hoặc chọn số bộ mặt người chơi
STR_FACE_FACECODE_SET :{WHITE}Mã số gương mặt mới được thiết lập.
STR_FACE_FACECODE_ERR :{WHITE}Không thể thiết lập mã số gương mặt - mã số phải trong khoảng từ 0 đến 4,294,967,295!
STR_FACE_FACECODE :{BLACK}Mã số khuôn mặt
STR_FACE_FACECODE_TOOLTIP :{BLACK}Xem và/hoặc sửa mã số gương mặt của chủ tịch công ty
STR_FACE_FACECODE_CAPTION :{WHITE}Xem và/hoặc chọn mã số gương mặt người chơi
STR_FACE_FACECODE_SET :{WHITE}Gương mặt người chơi mới được thiết lập.
STR_FACE_FACECODE_ERR :{WHITE}Không thể thiết lập mã số gương mặt - Nhãn và mã số phải hợp lệ
STR_FACE_SAVE :{BLACK}Lưu
STR_FACE_SAVE_TOOLTIP :{BLACK}Lưu gương mặt yêu thích
STR_FACE_SAVE_DONE :{WHITE}Gương mặt yêu thích này sẽ được lưu lại trong tập tin cấu hình OpenTTD .
STR_FACE_SETTING_TOGGLE :{STRING} {ORANGE}{STRING}
STR_FACE_SETTING_NUMERIC :{STRING} {ORANGE}{NUM} / {NUM}
STR_FACE_YES :Đồng ý
STR_FACE_NO :Không
STR_FACE_STYLE :Kiểu:
STR_FACE_HAIR :Tóc:
STR_FACE_EYEBROWS :Lông mày:
STR_FACE_EYECOLOUR :Màu mắt:
@ -2607,7 +2638,7 @@ STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} r
STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} đã đổi tên thành {STRING}
STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} tặng {CURRENCY_LONG} cho {STRING}
STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Server kết thúc phiên
STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Server khởi động lại...{}Xin chờ...
STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Server khởi động lại...{}{}Xin chờ...
STR_NETWORK_MESSAGE_KICKED :*** {STRING} đã bị đá khỏi ván chơi. Lý do: ({STRING})
STR_NETWORK_ERROR_COORDINATOR_REGISTRATION_FAILED :{WHITE}Đăng ký server thất bại
@ -2793,6 +2824,10 @@ STR_PICKER_MODE_USED_TOOLTIP :Bật/tắt hi
STR_PICKER_MODE_SAVED :Đã lưu
STR_PICKER_MODE_SAVED_TOOLTIP :Bật/tắt hiển thị những hạng mục được lưu
STR_PICKER_PREVIEW_SHRINK :-
STR_PICKER_PREVIEW_SHRINK_TOOLTIP :Giảm chiều cao của ảnh xem trước. Ctrl+Click để giảm đến mức tối thiểu
STR_PICKER_PREVIEW_EXPAND :+
STR_PICKER_PREVIEW_EXPAND_TOOLTIP :Tăng chiều cao của ảnh xem trước. Ctrl+Click để tăng đến mức tối đa
STR_PICKER_STATION_CLASS_TOOLTIP :Chọn loại ga bến cần hiển thị
STR_PICKER_STATION_TYPE_TOOLTIP :Chọn loại ga bến để xây. Ctrl+Click để thêm hoặc bớt vào danh sách lưu
@ -2816,6 +2851,7 @@ STR_HOUSE_PICKER_YEARS_FROM :{BLACK}Năm: {O
STR_HOUSE_PICKER_YEARS_UNTIL :{BLACK}Năm: {ORANGE}Đến {NUM}
STR_HOUSE_PICKER_SIZE :{BLACK}Kích thước: {ORANGE}{NUM}x{NUM} ô
STR_HOUSE_PICKER_CARGO_ACCEPTED :{BLACK}Hàng hóa được chấp nhận: {ORANGE}
STR_HOUSE_PICKER_CARGO_PRODUCED :{BLACK}Hàng hóa cung cấp: {ORANGE}{CARGO_LIST}
STR_HOUSE_PICKER_CLASS_ZONE1 :Ngoài rìa
STR_HOUSE_PICKER_CLASS_ZONE2 :Ngoại ô
@ -2824,6 +2860,7 @@ STR_HOUSE_PICKER_CLASS_ZONE4 :Phía trong ngo
STR_HOUSE_PICKER_CLASS_ZONE5 :Nội thành
STR_HOUSE_PICKER_PROTECT_TITLE :Ngăn chặn nâng cấp
STR_HOUSE_PICKER_PROTECT_TOOLTIP :Chọn nếu ngôi nhà này có được bảo vệ khỏi việc bị thay thế hay không khi thị trấn phát triển
STR_HOUSE_PICKER_PROTECT_OFF :Tắt
STR_HOUSE_PICKER_PROTECT_ON :Bật
@ -3031,6 +3068,11 @@ STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP :{BLACK}Chọn q
STR_FOUND_TOWN_CITY :{BLACK}Đô thị
STR_FOUND_TOWN_CITY_TOOLTIP :{BLACK}Thành phố phát triển nhanh hơn thị trấn{}Tuỳ thuộc thiết lập, chúng lớn hơn khi khai sinh
STR_FOUND_TOWN_EXPAND_MODE :{YELLOW}Mở rộng thị trấn:
STR_FOUND_TOWN_EXPAND_BUILDINGS :Công trình
STR_FOUND_TOWN_EXPAND_BUILDINGS_TOOLTIP :Tăng số công trình của thị trấn
STR_FOUND_TOWN_EXPAND_ROADS :Đường sá
STR_FOUND_TOWN_EXPAND_ROADS_TOOLTIP :Tăng số đường sá của thị trấn
STR_FOUND_TOWN_ROAD_LAYOUT :{YELLOW}Quy hoạch đường đô thị:
STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP :{BLACK}Chọn để quy hoạch đường bộ trong đô thị
@ -3103,6 +3145,8 @@ STR_LANG_AREA_INFORMATION_TRAM_TYPE :{BLACK}Kiểu x
STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT :{BLACK}Giới hạn tốc độ đường ray: {LTBLUE}{VELOCITY}
STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT :{BLACK}Hạn chế tốc độ đường bộ: {LTBLUE}{VELOCITY}
STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT :{BLACK}Tốc độ xe điện giới hạn: {LTBLUE}{VELOCITY}
STR_LAND_AREA_INFORMATION_TOWN_CAN_UPGRADE :{BLACK}Nâng cấp thị trấn: {LTBLUE}Có thể
STR_LAND_AREA_INFORMATION_TOWN_CANNOT_UPGRADE :{BLACK}Nâng cấp thị trấn: {LTBLUE}Không thể
# Description of land area of different tiles
STR_LAI_CLEAR_DESCRIPTION_ROCKS :Đá
@ -3111,6 +3155,9 @@ STR_LAI_CLEAR_DESCRIPTION_BARE_LAND :Đất trống
STR_LAI_CLEAR_DESCRIPTION_GRASS :Bãi cỏ
STR_LAI_CLEAR_DESCRIPTION_FIELDS :Cánh đồng
STR_LAI_CLEAR_DESCRIPTION_DESERT :Hoang mạc
STR_LAI_CLEAR_DESCRIPTION_SNOWY_ROCKS :Đá có tuyết phủ
STR_LAI_CLEAR_DESCRIPTION_SNOWY_ROUGH_LAND :Đất gồ ghề có tuyết phủ
STR_LAI_CLEAR_DESCRIPTION_SNOWY_GRASS :Cỏ có tuyết phủ
STR_LAI_RAIL_DESCRIPTION_TRACK :Đường ray
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_SIGNALS :Đường ray với đèn hiệu khóa
@ -3579,17 +3626,17 @@ STR_NEWGRF_LIST_COMPATIBLE :{YELLOW}Đã t
STR_NEWGRF_LIST_MISSING :{RED}Thiếu files
# NewGRF 'it's broken' warnings
STR_NEWGRF_BROKEN :{WHITE}Hoạt động của NewGRF '{0:STRING}' có thể gây mất đồng bộ hoặc bị treo.
STR_NEWGRF_BROKEN_POWERED_WAGON :{WHITE}Trạng thái đầu kéo '{1:ENGINE}' được thay đổi khi không ở trong xưởng sửa chữa.
STR_NEWGRF_BROKEN_VEHICLE_LENGTH :{WHITE}Nó cắt ngắn độ dài của đoàn tàu '{1:ENGINE}' nếu không ở trong xưởng.
STR_NEWGRF_BROKEN_CAPACITY :{WHITE}Sức chứa của phương tiện bị thay đổi '{1:ENGINE}' khi không ở trong xưởng hoặc vì cải biến
STR_NEWGRF_BROKEN :{WHITE}Hoạt động của NewGRF '{PUSH_COLOUR}{0:STRING}{POP_COLOUR}' có thể gây mất đồng bộ hoặc bị treo.
STR_NEWGRF_BROKEN_POWERED_WAGON :{WHITE}Trạng thái đầu kéo '{PUSH_COLOUR}{1:ENGINE}{POP_COLOUR}' được thay đổi khi không ở trong xưởng sửa chữa.
STR_NEWGRF_BROKEN_VEHICLE_LENGTH :{WHITE}Nó cắt ngắn độ dài của đoàn tàu '{PUSH_COLOUR}{1:ENGINE}{POP_COLOUR}' nếu không ở trong xưởng.
STR_NEWGRF_BROKEN_CAPACITY :{WHITE}Sức chứa của phương tiện bị thay đổi '{PUSH_COLOUR}{1:ENGINE}{POP_COLOUR}' khi không ở trong xưởng hoặc vì cải biến
STR_BROKEN_VEHICLE_LENGTH :{WHITE}Đoàn tàu '{VEHICLE}' của '{COMPANY}' có độ dài không hợp lệ. Sự cố có thể có căn nguyên từ NewGRFs. Ván chơi có thể mất đồng bộ hoặc bị treo
STR_NEWGRF_BUGGY :{WHITE}NewGRF '{0:STRING}' không hợp lệ.
STR_NEWGRF_BUGGY_ARTICULATED_CARGO :{WHITE}Danh mục hàng hoá/cải biến được cho '{1:ENGINE}' khác với danh mục mua được sau khi đã có. Việc này khiến cho việc tự thay thế hay là tự cải biến không chính xác.
STR_NEWGRF_BUGGY_ENDLESS_PRODUCTION_CALLBACK :{WHITE}'{1:STRING}' gây ra một vòng lặp vô tận khi gọi hàm callback.
STR_NEWGRF_BUGGY :{WHITE}NewGRF '{PUSH_COLOUR}{0:STRING}{POP_COLOUR}' không hợp lệ.
STR_NEWGRF_BUGGY_ARTICULATED_CARGO :{WHITE}Danh mục hàng hoá/cải biến được cho '{PUSH_COLOUR}{1:ENGINE}{POP_COLOUR}' khác với danh mục mua được sau khi đã có. Việc này khiến cho việc tự thay thế hay là tự cải biến không chính xác.
STR_NEWGRF_BUGGY_ENDLESS_PRODUCTION_CALLBACK :{WHITE}'{PUSH_COLOUR}{1:STRING}{POP_COLOUR}' gây ra một vòng lặp vô tận khi gọi hàm callback.
STR_NEWGRF_BUGGY_UNKNOWN_CALLBACK_RESULT :{WHITE}Hàm callback {1:HEX} gửi trả kết quả sai/không rõ {2:HEX}
STR_NEWGRF_BUGGY_INVALID_CARGO_PRODUCTION_CALLBACK :{WHITE}'{1:STRING}' trả về loại hàng hoá sản xuất không hợp lệ khi gọi lại tại {2:HEX}
STR_NEWGRF_BUGGY_INVALID_CARGO_PRODUCTION_CALLBACK :{WHITE}'{PUSH_COLOUR}{1:STRING}{POP_COLOUR}' trả về loại hàng hoá sản xuất không hợp lệ khi gọi lại tại {2:HEX}
# 'User removed essential NewGRFs'-placeholders for stuff without specs
STR_NEWGRF_INVALID_CARGO :<sai kiểu hàng>
@ -3650,6 +3697,10 @@ STR_TOWN_VIEW_RENAME_TOOLTIP :{BLACK}Đổi t
STR_TOWN_VIEW_EXPAND_BUTTON :{BLACK}Mở rộng
STR_TOWN_VIEW_EXPAND_TOOLTIP :{BLACK}Tăng quy mô đô thị
STR_TOWN_VIEW_EXPAND_BUILDINGS_BUTTON :{BLACK}Mở rộng công trình
STR_TOWN_VIEW_EXPAND_BUILDINGS_TOOLTIP :{BLACK}Tăng số công trình của thị trấn
STR_TOWN_VIEW_EXPAND_ROADS_BUTTON :{BLACK}Mở rộng đường
STR_TOWN_VIEW_EXPAND_ROADS_TOOLTIP :{BLACK}Tăng số đường sá của thị trấn
STR_TOWN_VIEW_DELETE_BUTTON :{BLACK}Xoá
STR_TOWN_VIEW_DELETE_TOOLTIP :{BLACK}Xoá bỏ đô thị này hoàn toàn
@ -3975,6 +4026,8 @@ STR_INDUSTRY_VIEW_PRODUCTION_LAST_MONTH_TITLE :{BLACK}Sản l
STR_INDUSTRY_VIEW_PRODUCTION_LAST_MINUTE_TITLE :{BLACK}Sản lượng phút trước:
STR_INDUSTRY_VIEW_TRANSPORTED :{YELLOW}{CARGO_LONG}{STRING}{BLACK} ({COMMA}% đã vận chuyển)
STR_INDUSTRY_VIEW_LOCATION_TOOLTIP :{BLACK}Xem vị trí trung tâm của nhà máy. Ctrl+Click mở cửa sổ mới để xem
STR_INDUSTRY_VIEW_CARGO_GRAPH :{BLACK}Đồ thị hàng hóa
STR_INDUSTRY_VIEW_CARGO_GRAPH_TOOLTIP :{BLACK}Xem đồ thị lịch sử kinh doanh hàng hóa
STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}Mức sản lượng: {YELLOW}{COMMA}%
STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}Nhà máy này đã thông báo sắp đóng cửa!
@ -4386,10 +4439,10 @@ STR_VEHICLE_VIEW_SHIP_ORDERS_TOOLTIP :{BLACK}Hiện l
STR_VEHICLE_VIEW_AIRCRAFT_ORDERS_TOOLTIP :{BLACK}Hiện lộ trình máy bay. Ctrl+Click để hiện lịch trình
###length VEHICLE_TYPES
STR_VEHICLE_VIEW_TRAIN_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết tàu hoả
STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết xe
STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết tàu thuỷ
STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết máy bay
STR_VEHICLE_VIEW_TRAIN_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết tàu hoả. Ctrl+Click vào để hiện nhóm của tàu hỏa
STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết xe. Ctrl+Click để hiện nhóm phương tiện
STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết tàu thuỷ. Ctrl+Click vào để hiện nhóm của tàu thủy
STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết máy bay. Ctrl+Click để hiện nhóm của máy bay
###length VEHICLE_TYPES
STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}Tác động đến tàu hỏa hiện tại - bấm để dừng/chạy tàu hỏa
@ -4644,55 +4697,56 @@ STR_ORDER_ROAD_VEHICLE_DEPOT :Xưởng xe
STR_ORDER_SHIP_DEPOT :Xưởng tàu thuỷ
###next-name-looks-similar
STR_ORDER_GO_TO_NEAREST_HANGAR_FORMAT :{STRING} xưởng sân bay gần nhất
STR_ORDER_GO_TO_NEAREST_DEPOT_FORMAT :{STRING} gần {STRING} nhất
STR_ORDER_GO_TO_DEPOT_FORMAT :{STRING} {DEPOT}
STR_ORDER_REFIT_ORDER :(Cải biến thành {STRING})
STR_ORDER_REFIT_STOP_ORDER :(Cải biến thành {STRING} và dừng)
STR_ORDER_STOP_ORDER :(Dừng)
STR_ORDER_REFIT_ORDER :{SPACE}(Cải biến thành {STRING})
STR_ORDER_REFIT_STOP_ORDER :{SPACE}(Cải biến thành {STRING} và dừng)
STR_ORDER_STOP_ORDER :{SPACE}(Dừng)
STR_ORDER_WAIT_TO_UNBUNCH :(Chờ để gỡ gộp)
STR_ORDER_WAIT_TO_UNBUNCH :{SPACE}(Chờ để gỡ gộp)
STR_ORDER_GO_TO_STATION :{STRING} {STATION}
STR_ORDER_GO_TO_STATION_CAN_T_USE_STATION :{PUSH_COLOUR}{RED}(Không thể sử dụng trạm){POP_COLOUR} {STRING} {STATION}
STR_ORDER_IMPLICIT :(Chạy ngầm)
STR_ORDER_IMPLICIT :{SPACE}(Chạy ngầm)
STR_ORDER_FULL_LOAD :(Bốc đầy hàng)
STR_ORDER_FULL_LOAD_ANY :(Bốc đủ bất kỳ hàng nào)
STR_ORDER_NO_LOAD :(Không bốc xếp)
STR_ORDER_UNLOAD :(Dỡ và lấy hàng khác)
STR_ORDER_UNLOAD_FULL_LOAD :(Dỡ tất hàng và chờ bốc đầy hàng)
STR_ORDER_UNLOAD_FULL_LOAD_ANY :(Dỡ tất hàng và chờ bốc đủ bất kỳ hàng nào)
STR_ORDER_UNLOAD_NO_LOAD :(Dỡ tất hàng và để trống)
STR_ORDER_TRANSFER :(Trung chuyển hàng và lấy hàng khác)
STR_ORDER_TRANSFER_FULL_LOAD :(Trung chuyển và chờ bốc đầy hàng)
STR_ORDER_TRANSFER_FULL_LOAD_ANY :(Trung chuyển và chờ bốc đủ hàng bất kỳ)
STR_ORDER_TRANSFER_NO_LOAD :(Trung chuyển và để trống)
STR_ORDER_NO_UNLOAD :(Không dỡ và lấy hàng)
STR_ORDER_NO_UNLOAD_FULL_LOAD :(Không dỡ và chờ lấy thêm đầy hàng)
STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY :(Không dỡ và chờ lấy đủ hàng bất kỳ)
STR_ORDER_NO_UNLOAD_NO_LOAD :(Không bốc hàng và không dỡ hàng)
STR_ORDER_FULL_LOAD :{SPACE}(Bốc đầy hàng)
STR_ORDER_FULL_LOAD_ANY :{SPACE}(Bốc đủ bất kỳ hàng nào)
STR_ORDER_NO_LOAD :{SPACE}(Không bốc xếp)
STR_ORDER_UNLOAD :{SPACE}(Dỡ và lấy hàng khác)
STR_ORDER_UNLOAD_FULL_LOAD :{SPACE}(Dỡ tất hàng và chờ bốc đầy hàng)
STR_ORDER_UNLOAD_FULL_LOAD_ANY :{SPACE}(Dỡ tất hàng và chờ bốc đủ bất kỳ hàng nào)
STR_ORDER_UNLOAD_NO_LOAD :{SPACE}(Dỡ tất hàng và để trống)
STR_ORDER_TRANSFER :{SPACE}(Trung chuyển hàng và lấy hàng khác)
STR_ORDER_TRANSFER_FULL_LOAD :{SPACE}(Trung chuyển và chờ bốc đầy hàng)
STR_ORDER_TRANSFER_FULL_LOAD_ANY :{SPACE}(Trung chuyển và chờ bốc đủ hàng bất kỳ)
STR_ORDER_TRANSFER_NO_LOAD :{SPACE}(Trung chuyển và để trống)
STR_ORDER_NO_UNLOAD :{SPACE}(Không dỡ và lấy hàng)
STR_ORDER_NO_UNLOAD_FULL_LOAD :{SPACE}(Không dỡ và chờ lấy thêm đầy hàng)
STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY :{SPACE}(Không dỡ và chờ lấy đủ hàng bất kỳ)
STR_ORDER_NO_UNLOAD_NO_LOAD :{SPACE}(Không bốc hàng và không dỡ hàng)
STR_ORDER_AUTO_REFIT :(Tự cải biến thành {STRING})
STR_ORDER_FULL_LOAD_REFIT :(Tự cải biến và chất đầy {STRING})
STR_ORDER_FULL_LOAD_ANY_REFIT :(Tự cải biến và chất đầy bất kỳ {STRING})
STR_ORDER_UNLOAD_REFIT :(Dỡ hàng và tự cải biến để lấy {STRING})
STR_ORDER_UNLOAD_FULL_LOAD_REFIT :(Dỡ hàng và tự cải biến đề bốc đầy {STRING})
STR_ORDER_UNLOAD_FULL_LOAD_ANY_REFIT :(Dỡ hàng và tự cải biến để bốc đầy bất kỳ {STRING})
STR_ORDER_TRANSFER_REFIT :(Trung chuyển và tự cải biến để lấy {STRING})
STR_ORDER_TRANSFER_FULL_LOAD_REFIT :(Trung chuyển và tự cải biến đề bốc đầy {STRING})
STR_ORDER_TRANSFER_FULL_LOAD_ANY_REFIT :(Trung chuyển và tự cải biến để bốc đầy bất kỳ {STRING})
STR_ORDER_NO_UNLOAD_REFIT :(Không dỡ hàng và tự cái biến để lấy {STRING})
STR_ORDER_NO_UNLOAD_FULL_LOAD_REFIT :(Không dỡ hàng và tự cải biến để bốc đầy {STRING})
STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY_REFIT :(Không dỡ hàng và tự cải biến để bốc đầy bất kỳ {STRING})
STR_ORDER_AUTO_REFIT :{SPACE}(Tự cải biến thành {STRING})
STR_ORDER_FULL_LOAD_REFIT :{SPACE}(Tự cải biến và chất đầy {STRING})
STR_ORDER_FULL_LOAD_ANY_REFIT :{SPACE}(Tự cải biến và chất đầy bất kỳ {STRING})
STR_ORDER_UNLOAD_REFIT :{SPACE}(Dỡ hàng và tự cải biến để lấy {STRING})
STR_ORDER_UNLOAD_FULL_LOAD_REFIT :{SPACE}(Dỡ hàng và tự cải biến đề bốc đầy {STRING})
STR_ORDER_UNLOAD_FULL_LOAD_ANY_REFIT :{SPACE}(Dỡ hàng và tự cải biến để bốc đầy bất kỳ {STRING})
STR_ORDER_TRANSFER_REFIT :{SPACE}(Trung chuyển và tự cải biến để lấy {STRING})
STR_ORDER_TRANSFER_FULL_LOAD_REFIT :{SPACE}(Trung chuyển và tự cải biến đề bốc đầy {STRING})
STR_ORDER_TRANSFER_FULL_LOAD_ANY_REFIT :{SPACE}(Trung chuyển và tự cải biến để bốc đầy bất kỳ {STRING})
STR_ORDER_NO_UNLOAD_REFIT :{SPACE}(Không dỡ hàng và tự cái biến để lấy {STRING})
STR_ORDER_NO_UNLOAD_FULL_LOAD_REFIT :{SPACE}(Không dỡ hàng và tự cải biến để bốc đầy {STRING})
STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY_REFIT :{SPACE}(Không dỡ hàng và tự cải biến để bốc đầy bất kỳ {STRING})
STR_ORDER_AUTO_REFIT_ANY :hàng hóa sẵn có
###length 3
STR_ORDER_STOP_LOCATION_NEAR_END :[đỗ ở đầu gần]
STR_ORDER_STOP_LOCATION_MIDDLE :[đỗ ở giữa]
STR_ORDER_STOP_LOCATION_FAR_END :[đỗ ở đầu xa]
STR_ORDER_STOP_LOCATION_NEAR_END :{SPACE}[đỗ ở đầu gần]
STR_ORDER_STOP_LOCATION_MIDDLE :{SPACE}[đỗ ở giữa]
STR_ORDER_STOP_LOCATION_FAR_END :{SPACE}[đỗ ở đầu xa]
STR_ORDER_OUT_OF_RANGE :{RED} (Điểm đến kế tiếp ngoài tầm xa)
@ -4712,14 +4766,15 @@ STR_TIMETABLE_TOOLTIP :{BLACK}Lịch t
STR_TIMETABLE_NO_TRAVEL :Không di chuyển
STR_TIMETABLE_NOT_TIMETABLEABLE :Hành trình (tự động; tính thời gian theo lịch trình thủ công kế tiếp)
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :Di chuyển (không bó buộc theo lịch trình)
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED :Hành trình với tốc độ tối đa là {VELOCITY} (chưa dựng lịch trình)
STR_TIMETABLE_TRAVEL_FOR :Di chuyển trong {STRING}
STR_TIMETABLE_TRAVEL_FOR_SPEED :Lộ trình {STRING} với tốc độ tối đa {VELOCITY}
STR_TIMETABLE_TRAVEL_FOR_ESTIMATED :Lộ trình (cho {STRING}, chưa có lịch trình)
STR_TIMETABLE_TRAVEL_FOR_SPEED_ESTIMATED :Lộ trình (cho {STRING}, chưa có lịch trình) với tốc độ đối đa {VELOCITY}
STR_TIMETABLE_STAY_FOR_ESTIMATED :(ở lại {STRING}, chưa có lịch trình)
STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED :(di chuyển đến {STRING}, chưa có lịch trình)
STR_TIMETABLE_STAY_FOR :và ở lại trong {STRING}
STR_TIMETABLE_AND_TRAVEL_FOR :và di chuyển trong {STRING}
STR_TIMETABLE_STAY_FOR_ESTIMATED :{SPACE}(ở lại {STRING}, chưa có lịch trình)
STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED :{SPACE}(di chuyển đến {STRING}, chưa có lịch trình)
STR_TIMETABLE_STAY_FOR :{SPACE}và ở lại trong {STRING}
STR_TIMETABLE_AND_TRAVEL_FOR :{SPACE}và di chuyển trong {STRING}
STR_TIMETABLE_APPROX_TIME :{BLACK}Lịch trình này sẽ mất khoảng {STRING} để hoàn thành
STR_TIMETABLE_TOTAL_TIME :{BLACK}Lịch trình này sẽ mất {STRING} để hoàn thành
@ -4738,12 +4793,14 @@ STR_TIMETABLE_START_SECONDS_QUERY :Số giây cho
STR_TIMETABLE_CHANGE_TIME :{BLACK}Đổi thời gian
STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Thay đổi thời lượng của điểm lộ trình được phép sử dụng. Ctrl+Click đặt thời gian cho mọi lộ trình
STR_TIMETABLE_CHANGE_TIME_QUERY :Thay đổi thời gian
STR_TIMETABLE_CLEAR_TIME :{BLACK}Xoá thời gian
STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Xóa thời lượng áp dụng cho điểm lộ trình. Ctrl+Click xoá tất cả thời gian cho mọi lộ trình
STR_TIMETABLE_CHANGE_SPEED :{BLACK}Thay Đổi Giới Hạn Tốc Độ
STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Thay đổi tốc độ tối đa của lộ trình được chọn. Ctrl+Click đặt tốc độ cho mọi lộ trình
STR_TIMETABLE_CHANGE_SPEED_QUERY :Thay đổi giới hạn tốc độ
STR_TIMETABLE_CLEAR_SPEED :{BLACK}Xóa Giới Hạn Tốc Độ
STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Xóa tốc độ đối đa đối với lộ trình được chọn. Ctrl+Click xoá tốc độ cho mọi lộ trình
@ -4907,7 +4964,7 @@ STR_GAME_SAVELOAD_NOT_AVAILABLE :<không có s
STR_WARNING_LOADGAME_REMOVED_TRAMS :{WHITE}Lưu ván chơi sẽ không có xe điện. Những công trình cho xe điện sẽ bị xoá bỏ
# Map generation messages
STR_ERROR_COULD_NOT_CREATE_TOWN :{WHITE}Sinh bản đồ bị ngưng...{}... không có nơi đặt đô thị
STR_ERROR_COULD_NOT_CREATE_TOWN :{WHITE}Sinh bản đồ bị ngưng...{}{}... không có nơi đặt đô thị
STR_ERROR_NO_TOWN_IN_SCENARIO :{WHITE}... không có đô thị nào ở màn chơi kịch bản này
STR_ERROR_PNGMAP :{WHITE}Không thể nạp nền từ file PNG...
@ -4946,6 +5003,7 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}Yêu c
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Tạo dốc bị sai hướng
STR_ERROR_CAN_T_DO_THIS :{WHITE}Không làm thế này được...
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Cần giải toả nhà cửa trước
STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}... công trình được bảo vệ
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Không thể dọn dẹp khu vực này...
STR_ERROR_SITE_UNSUITABLE :{WHITE}... điểm không phù hợp
STR_ERROR_ALREADY_BUILT :{WHITE}... đã xây rồi
@ -4998,7 +5056,7 @@ STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... quá
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... quá nhiều đô thị
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... không còn khoảng trống nào trên bản đồ
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Xây dựng cầu đường đang tiến hành
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Không thể xoá đo thị này...{}Có một ga, bến hoặc xưởng thuộc đô thị hoặc là 1 ô đất của đô thị không thể xoá được.
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Không thể xoá đo thị này...{}{}Có một ga, bến hoặc xưởng thuộc đô thị hoặc là 1 ô đất của đô thị không thể xoá được.
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... không có nơi nào hợp lý để dựng tượng đài ở trung tâm đô thị này
STR_ERROR_CAN_T_BUILD_HOUSE :{WHITE}Không thể xây dựng nhà...
@ -5825,6 +5883,7 @@ STR_CURRENCY_SHORT_GIGA :{NBSP}tỷ
STR_CURRENCY_SHORT_TERA :{NBSP}ktỷ
STR_JUST_CARGO :{CARGO_LONG}
STR_JUST_LEFT_ARROW :{LEFT_ARROW}
STR_JUST_RIGHT_ARROW :{RIGHT_ARROW}
STR_JUST_CHECKMARK :{CHECKMARK}
STR_JUST_COMMA :{COMMA}
@ -5864,3 +5923,11 @@ STR_SHIP :{BLACK}{SHIP}
STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY})
STR_BADGE_NAME_LIST :{STRING}: {GOLD}{STRING}
STR_BADGE_CONFIG_MENU_TOOLTIP :Mở thiết lập phù hiệu
STR_BADGE_CONFIG_RESET :Thiêt lập lại
STR_BADGE_CONFIG_ICONS :{WHITE}Ảnh phù hiệu
STR_BADGE_CONFIG_FILTERS :{WHITE}Bộ lọc phù hiệu
STR_BADGE_CONFIG_PREVIEW :Ảnh xem trước
STR_BADGE_CONFIG_NAME :Tên
STR_BADGE_FILTER_ANY_LABEL :Bất cứ {STRING} nào
STR_BADGE_FILTER_IS_LABEL :{STRING} là {STRING}

View File

@ -599,7 +599,7 @@ static CommandCost ClearTile_Object(TileIndex tile, DoCommandFlags flags)
if (flags.Test(DoCommandFlag::Execute)) {
Town *town = o->town;
town->statues.Reset(GetTileOwner(tile));
SetWindowDirty(WC_TOWN_AUTHORITY, town->index);
SetWindowDirty(WC_TOWN_VIEW, town->index);
}
break;
@ -882,7 +882,7 @@ static void ChangeTileOwner_Object(TileIndex tile, Owner old_owner, Owner new_ow
do_clear = true;
}
SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
SetWindowDirty(WC_TOWN_VIEW, t->index);
} else {
do_clear = true;
}

View File

@ -147,7 +147,7 @@ def = true
str = STR_CONFIG_SETTING_BRIBE
strhelp = STR_CONFIG_SETTING_BRIBE_HELPTEXT
help_cb = SettingHelpWallclock
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_AUTHORITY); }
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_VIEW); }
cat = SC_BASIC
[SDT_BOOL]
@ -157,7 +157,7 @@ def = true
str = STR_CONFIG_SETTING_ALLOW_EXCLUSIVE
strhelp = STR_CONFIG_SETTING_ALLOW_EXCLUSIVE_HELPTEXT
help_cb = SettingHelpWallclock
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_AUTHORITY); }
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_VIEW); }
cat = SC_BASIC
[SDT_BOOL]
@ -166,7 +166,7 @@ from = SLV_165
def = true
str = STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS
strhelp = STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS_HELPTEXT
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_AUTHORITY); }
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_VIEW); }
cat = SC_BASIC
[SDT_BOOL]
@ -175,7 +175,7 @@ from = SLV_160
def = true
str = STR_CONFIG_SETTING_ALLOW_FUND_ROAD
strhelp = STR_CONFIG_SETTING_ALLOW_FUND_ROAD_HELPTEXT
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_AUTHORITY); }
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_VIEW); }
cat = SC_BASIC
[SDT_BOOL]

View File

@ -3187,7 +3187,7 @@ CommandCost CmdTownRating(DoCommandFlags flags, TownID town_id, CompanyID compan
int16_t new_rating = Clamp(rating, RATING_MINIMUM, RATING_MAXIMUM);
if (flags.Test(DoCommandFlag::Execute)) {
t->ratings[company_id] = new_rating;
InvalidateWindowData(WC_TOWN_AUTHORITY, town_id);
InvalidateWindowData(WC_TOWN_VIEW, town_id);
}
return CommandCost();
@ -3583,7 +3583,7 @@ static CommandCost TownActionBribe(Town *t, DoCommandFlags flags)
*/
if (t->ratings[_current_company] > RATING_BRIBE_DOWN_TO) {
t->ratings[_current_company] = RATING_BRIBE_DOWN_TO;
SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
SetWindowDirty(WC_TOWN_VIEW, t->index);
}
} else {
ChangeTownRating(t, RATING_BRIBE_UP_STEP, RATING_BRIBE_MAXIMUM, DoCommandFlag::Execute);
@ -3684,7 +3684,7 @@ CommandCost CmdDoTownAction(DoCommandFlags flags, TownID town_id, TownAction act
if (ret.Failed()) return ret;
if (flags.Test(DoCommandFlag::Execute)) {
SetWindowDirty(WC_TOWN_AUTHORITY, town_id);
SetWindowDirty(WC_TOWN_VIEW, town_id);
}
return cost;
@ -3737,7 +3737,7 @@ static void UpdateTownRating(Town *t)
t->ratings[i] = Clamp(t->ratings[i], RATING_MINIMUM, RATING_MAXIMUM);
}
SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
SetWindowDirty(WC_TOWN_VIEW, t->index);
}
@ -4009,7 +4009,7 @@ void ChangeTownRating(Town *t, int add, int max, DoCommandFlags flags)
} else {
t->have_ratings.Set(_current_company);
t->ratings[_current_company] = rating;
SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
InvalidateWindowData(WC_TOWN_VIEW, t->index);
}
}

View File

@ -57,36 +57,21 @@ TownKdtree _town_local_authority_kdtree{};
typedef GUIList<const Town*, const bool &> GUITownList;
static constexpr NWidgetPart _nested_town_authority_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
NWidget(WWT_CAPTION, COLOUR_BROWN, WID_TA_CAPTION),
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TA_ZONE_BUTTON), SetMinimalSize(50, 0), SetStringTip(STR_LOCAL_AUTHORITY_ZONE, STR_LOCAL_AUTHORITY_ZONE_TOOLTIP),
NWidget(WWT_SHADEBOX, COLOUR_BROWN),
NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
NWidget(WWT_STICKYBOX, COLOUR_BROWN),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_RATING_INFO), SetMinimalSize(317, 92), SetResize(1, 1), EndContainer(),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_COMMAND_LIST), SetMinimalSize(317, 52), SetResize(1, 0), SetToolTip(STR_LOCAL_AUTHORITY_ACTIONS_TOOLTIP), EndContainer(),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_ACTION_INFO), SetMinimalSize(317, 52), SetResize(1, 0), EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TA_EXECUTE), SetMinimalSize(317, 12), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_LOCAL_AUTHORITY_DO_IT_BUTTON, STR_LOCAL_AUTHORITY_DO_IT_TOOLTIP),
NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
EndContainer()
};
/** Town authority window. */
struct TownAuthorityWindow : Window {
/* Town view window. */
struct TownViewWindow : Window {
private:
Town *town = nullptr; ///< Town being displayed.
Town *town = nullptr; ///< Town displayed by the window.
TownAction sel_action = TownAction::End; ///< Currently selected town action, TownAction::End means no action selected.
TownActions displayed_actions_on_previous_painting{}; ///< Actions that were available on the previous call to OnPaint()
TownActions enabled_actions{}; ///< Actions that are enabled in settings.
TownActions available_actions{}; ///< Actions that are available to execute for the current company.
std::array<StringID, to_underlying(TownAction::End)> action_tooltips{};
Dimension icon_size{}; ///< Dimensions of company icon
Dimension exclusive_size{}; ///< Dimensions of exclusive icon
uint rating_line_height = 0;
static inline uint initial_visible_pane = 0;
uint visible_pane = 0;
/**
* Gets all town authority actions enabled in settings.
@ -107,10 +92,17 @@ private:
}
public:
TownAuthorityWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc)
static const int WID_TV_HEIGHT_NORMAL = 150;
TownViewWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc)
{
this->visible_pane = TownViewWindow::initial_visible_pane;
this->CreateNestedTree();
this->town = Town::Get(window_number);
this->enabled_actions = GetEnabledActions();
this->available_actions = GetMaskOfTownActions(_local_company, this->town);
auto realtime = TimerGameEconomy::UsingWallclockUnits();
this->action_tooltips[0] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING;
@ -122,238 +114,7 @@ public:
this->action_tooltips[6] = realtime ? STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT_MINUTES : STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT_MONTHS;
this->action_tooltips[7] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE;
this->InitNested(window_number);
}
void OnInit() override
{
this->icon_size = GetSpriteSize(SPR_COMPANY_ICON);
this->exclusive_size = GetSpriteSize(SPR_EXCLUSIVE_TRANSPORT);
}
void OnPaint() override
{
this->available_actions = GetMaskOfTownActions(_local_company, this->town);
if (this->available_actions != displayed_actions_on_previous_painting) this->SetDirty();
displayed_actions_on_previous_painting = this->available_actions;
this->SetWidgetLoweredState(WID_TA_ZONE_BUTTON, this->town->show_zone);
this->SetWidgetDisabledState(WID_TA_EXECUTE, (this->sel_action == TownAction::End) || !this->available_actions.Test(this->sel_action));
this->DrawWidgets();
if (!this->IsShaded())
{
this->DrawRatings();
this->DrawActions();
}
}
StringID GetRatingString(int rating) const
{
if (rating > RATING_EXCELLENT) return STR_CARGO_RATING_OUTSTANDING;
if (rating > RATING_VERYGOOD) return STR_CARGO_RATING_EXCELLENT;
if (rating > RATING_GOOD) return STR_CARGO_RATING_VERY_GOOD;
if (rating > RATING_MEDIOCRE) return STR_CARGO_RATING_GOOD;
if (rating > RATING_POOR) return STR_CARGO_RATING_MEDIOCRE;
if (rating > RATING_VERYPOOR) return STR_CARGO_RATING_POOR;
if (rating > RATING_APPALLING) return STR_CARGO_RATING_VERY_POOR;
return STR_CARGO_RATING_APPALLING;
}
/** Draw the contents of the ratings panel. May request a resize of the window if the contents does not fit. */
void DrawRatings()
{
Rect r = this->GetWidget<NWidgetBase>(WID_TA_RATING_INFO)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
int text_y_offset = (this->resize.step_height - GetCharacterHeight(FS_NORMAL)) / 2;
int icon_y_offset = (this->resize.step_height - this->icon_size.height) / 2;
int exclusive_y_offset = (this->resize.step_height - this->exclusive_size.height) / 2;
DrawString(r.left, r.right, r.top + text_y_offset, STR_LOCAL_AUTHORITY_COMPANY_RATINGS);
r.top += this->resize.step_height;
bool rtl = _current_text_dir == TD_RTL;
Rect icon = r.WithWidth(this->icon_size.width, rtl);
Rect exclusive = r.Indent(this->icon_size.width + WidgetDimensions::scaled.hsep_normal, rtl).WithWidth(this->exclusive_size.width, rtl);
Rect text = r.Indent(this->icon_size.width + WidgetDimensions::scaled.hsep_normal + this->exclusive_size.width + WidgetDimensions::scaled.hsep_normal, rtl);
/* Draw list of companies */
for (const Company *c : Company::Iterate()) {
if ((this->town->have_ratings.Test(c->index) || this->town->exclusivity == c->index)) {
DrawCompanyIcon(c->index, icon.left, text.top + icon_y_offset);
if (this->town->exclusivity == c->index) {
DrawSprite(SPR_EXCLUSIVE_TRANSPORT, GetCompanyPalette(c->index), exclusive.left, text.top + exclusive_y_offset);
}
int rating = this->town->ratings[c->index];
DrawString(text.left, text.right, text.top + text_y_offset, GetString(STR_LOCAL_AUTHORITY_COMPANY_RATING, c->index, c->index, GetRatingString(rating)));
text.top += this->resize.step_height;
}
}
text.bottom = text.top - 1;
if (text.bottom > r.bottom) {
/* If the company list is too big to fit, mark ourself dirty and draw again. */
ResizeWindow(this, 0, text.bottom - r.bottom, false);
}
}
/** Draws the contents of the actions panel. May re-initialise window to resize panel, if the list does not fit. */
void DrawActions()
{
Rect r = this->GetWidget<NWidgetBase>(WID_TA_COMMAND_LIST)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
DrawString(r, STR_LOCAL_AUTHORITY_ACTIONS_TITLE);
r.top += GetCharacterHeight(FS_NORMAL);
/* Draw list of actions */
for (TownAction i = {}; i != TownAction::End; ++i) {
/* Don't show actions if disabled in settings. */
if (!this->enabled_actions.Test(i)) continue;
/* Set colour of action based on ability to execute and if selected. */
TextColour action_colour = TC_GREY | TC_NO_SHADE;
if (this->available_actions.Test(i)) action_colour = TC_ORANGE;
if (this->sel_action == i) action_colour = TC_WHITE;
DrawString(r, STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + to_underlying(i), action_colour);
r.top += GetCharacterHeight(FS_NORMAL);
}
}
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
{
if (widget == WID_TA_CAPTION) return GetString(STR_LOCAL_AUTHORITY_CAPTION, this->window_number);
return this->Window::GetWidgetString(widget, stringid);
}
void DrawWidget(const Rect &r, WidgetID widget) const override
{
switch (widget) {
case WID_TA_ACTION_INFO:
if (this->sel_action != TownAction::End) {
Money action_cost = _price[PR_TOWN_ACTION] * GetTownActionCost(this->sel_action) >> 8;
bool affordable = Company::IsValidID(_local_company) && action_cost < GetAvailableMoney(_local_company);
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.framerect),
GetString(this->action_tooltips[to_underlying(this->sel_action)], action_cost),
affordable ? TC_YELLOW : TC_RED);
}
break;
}
}
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
{
switch (widget) {
case WID_TA_ACTION_INFO: {
assert(size.width > padding.width && size.height > padding.height);
Dimension d = {0, 0};
for (TownAction i = {}; i != TownAction::End; ++i) {
Money price = _price[PR_TOWN_ACTION] * GetTownActionCost(i) >> 8;
d = maxdim(d, GetStringMultiLineBoundingBox(GetString(this->action_tooltips[to_underlying(i)], price), size));
}
d.width += padding.width;
d.height += padding.height;
size = maxdim(size, d);
break;
}
case WID_TA_COMMAND_LIST:
size.height = (to_underlying(TownAction::End) + 1) * GetCharacterHeight(FS_NORMAL) + padding.height;
size.width = GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTIONS_TITLE).width;
for (TownAction i = {}; i != TownAction::End; ++i) {
size.width = std::max(size.width, GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + to_underlying(i)).width + padding.width);
}
size.width += padding.width;
break;
case WID_TA_RATING_INFO:
fill.height = resize.height = std::max({this->icon_size.height + WidgetDimensions::scaled.vsep_normal, this->exclusive_size.height + WidgetDimensions::scaled.vsep_normal, (uint)GetCharacterHeight(FS_NORMAL)});
size.height = 9 * resize.height + padding.height;
break;
}
}
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
switch (widget) {
case WID_TA_ZONE_BUTTON: {
bool new_show_state = !this->town->show_zone;
TownID index = this->town->index;
new_show_state ? _town_local_authority_kdtree.Insert(index) : _town_local_authority_kdtree.Remove(index);
this->town->show_zone = new_show_state;
this->SetWidgetLoweredState(widget, new_show_state);
MarkWholeScreenDirty();
break;
}
case WID_TA_COMMAND_LIST: {
int y = this->GetRowFromWidget(pt.y, WID_TA_COMMAND_LIST, 1, GetCharacterHeight(FS_NORMAL)) - 1;
auto action = this->enabled_actions.GetNthSetBit(y);
if (!action.has_value()) break;
this->sel_action = *action;
this->SetDirty();
/* When double-clicking, continue */
if (click_count == 1 || !this->available_actions.Test(this->sel_action)) break;
[[fallthrough]];
}
case WID_TA_EXECUTE:
Command<CMD_DO_TOWN_ACTION>::Post(STR_ERROR_CAN_T_DO_THIS, this->town->xy, static_cast<TownID>(this->window_number), this->sel_action);
break;
}
}
/** Redraw the whole window on a regular interval. */
const IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(3), [this](auto) {
this->SetDirty();
}};
void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
{
if (!gui_scope) return;
this->enabled_actions = this->GetEnabledActions();
if (!this->enabled_actions.Test(this->sel_action)) {
this->sel_action = TownAction::End;
}
}
};
static WindowDesc _town_authority_desc(
WDP_AUTO, "view_town_authority", 317, 222,
WC_TOWN_AUTHORITY, WC_NONE,
{},
_nested_town_authority_widgets
);
static void ShowTownAuthorityWindow(uint town)
{
AllocateWindowDescFront<TownAuthorityWindow>(_town_authority_desc, town);
}
/* Town view window. */
struct TownViewWindow : Window {
private:
Town *town = nullptr; ///< Town displayed by the window.
public:
static const int WID_TV_HEIGHT_NORMAL = 150;
TownViewWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc)
{
this->CreateNestedTree();
this->town = Town::Get(window_number);
this->SetPaneState();
this->FinishInitNested(window_number);
@ -365,6 +126,23 @@ public:
this->SetWidgetDisabledState(WID_TV_CHANGE_NAME, _networking && !_network_server);
}
void SetPaneState()
{
if (auto *nwid = this->GetWidget<NWidgetStacked>(WID_TV_PANE_SEL); nwid != nullptr) {
nwid->SetDisplayedPlane(this->visible_pane);
this->SetWidgetLoweredState(WID_TV_PANE_INFO, this->visible_pane == 0);
this->SetWidgetLoweredState(WID_TV_PANE_RATINGS, this->visible_pane == 1);
this->SetWidgetLoweredState(WID_TV_PANE_ACTIONS, this->visible_pane == 2);
}
}
void OnInit() override
{
this->icon_size = GetScaledSpriteSize(SPR_COMPANY_ICON);
this->exclusive_size = GetScaledSpriteSize(SPR_EXCLUSIVE_TRANSPORT);
this->rating_line_height = std::max({this->icon_size.height, this->exclusive_size.height, (uint)GetCharacterHeight(FS_NORMAL)});
}
void Close([[maybe_unused]] int data = 0) override
{
SetViewportCatchmentTown(Town::Get(this->window_number), false);
@ -382,14 +160,24 @@ public:
{
extern const Town *_viewport_highlight_town;
this->SetWidgetLoweredState(WID_TV_CATCHMENT, _viewport_highlight_town == this->town);
this->SetWidgetLoweredState(WID_TV_ZONE, this->town->show_zone);
this->SetWidgetDisabledState(WID_TV_EXECUTE, this->visible_pane != 2 || this->sel_action == TownAction::End || !this->available_actions.Test(this->sel_action));
this->DrawWidgets();
}
void DrawWidget(const Rect &r, WidgetID widget) const override
{
if (widget != WID_TV_INFO) return;
switch (widget) {
case WID_TV_INFO: this->DrawInfo(r); break;
case WID_TV_RATING_INFO: this->DrawRatings(r); break;
case WID_TV_COMMAND_LIST: this->DrawActions(r); break;
case WID_TV_ACTION_INFO: this->DrawActionInfo(r); break;
default: break;
}
}
void DrawInfo(const Rect &r) const
{
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
DrawString(tr, GetString(STR_TOWN_VIEW_POPULATION_HOUSES, this->town->cache.population, this->town->cache.num_houses));
@ -465,6 +253,86 @@ public:
}
}
static StringID GetRatingString(int rating)
{
if (rating > RATING_EXCELLENT) return STR_CARGO_RATING_OUTSTANDING;
if (rating > RATING_VERYGOOD) return STR_CARGO_RATING_EXCELLENT;
if (rating > RATING_GOOD) return STR_CARGO_RATING_VERY_GOOD;
if (rating > RATING_MEDIOCRE) return STR_CARGO_RATING_GOOD;
if (rating > RATING_POOR) return STR_CARGO_RATING_MEDIOCRE;
if (rating > RATING_VERYPOOR) return STR_CARGO_RATING_POOR;
if (rating > RATING_APPALLING) return STR_CARGO_RATING_VERY_POOR;
return STR_CARGO_RATING_APPALLING;
}
/** Draw the contents of the ratings panel. May request a resize of the window if the contents does not fit. */
void DrawRatings(const Rect &r) const
{
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
int text_y_offset = (this->rating_line_height - GetCharacterHeight(FS_NORMAL)) / 2;
int icon_y_offset = (this->rating_line_height - this->icon_size.height) / 2;
int exclusive_y_offset = (this->rating_line_height - this->exclusive_size.height) / 2;
DrawString(tr.left, tr.right, tr.top + text_y_offset, STR_LOCAL_AUTHORITY_COMPANY_RATINGS);
tr.top += this->rating_line_height;
bool rtl = _current_text_dir == TD_RTL;
Rect icon = tr.WithWidth(this->icon_size.width, rtl);
Rect exclusive = tr.Indent(this->icon_size.width + WidgetDimensions::scaled.hsep_normal, rtl).WithWidth(this->exclusive_size.width, rtl);
Rect text = tr.Indent(this->icon_size.width + WidgetDimensions::scaled.hsep_normal + this->exclusive_size.width + WidgetDimensions::scaled.hsep_normal, rtl);
/* Draw list of companies */
for (const Company *c : Company::Iterate()) {
if ((this->town->have_ratings.Test(c->index) || this->town->exclusivity == c->index)) {
DrawCompanyIcon(c->index, icon.left, text.top + icon_y_offset);
if (this->town->exclusivity == c->index) {
DrawSprite(SPR_EXCLUSIVE_TRANSPORT, GetCompanyPalette(c->index), exclusive.left, text.top + exclusive_y_offset);
}
int rating = this->town->ratings[c->index];
DrawString(text.left, text.right, text.top + text_y_offset, GetString(STR_LOCAL_AUTHORITY_COMPANY_RATING, c->index, c->index, GetRatingString(rating)));
text.top += this->rating_line_height;
}
}
}
/** Draws the contents of the actions panel. May re-initialise window to resize panel, if the list does not fit. */
void DrawActions(const Rect &r) const
{
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
DrawString(tr, STR_LOCAL_AUTHORITY_ACTIONS_TITLE);
tr.top += GetCharacterHeight(FS_NORMAL);
/* Draw list of actions */
for (TownAction i = {}; i != TownAction::End; ++i) {
/* Don't show actions if disabled in settings. */
if (!this->enabled_actions.Test(i)) continue;
/* Set colour of action based on ability to execute and if selected. */
TextColour action_colour = TC_GREY | TC_NO_SHADE;
if (this->available_actions.Test(i)) action_colour = TC_ORANGE;
if (this->sel_action == i) action_colour = TC_WHITE;
DrawString(tr, STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + to_underlying(i), action_colour);
tr.top += GetCharacterHeight(FS_NORMAL);
}
}
void DrawActionInfo(const Rect &r) const
{
if (this->sel_action == TownAction::End) return;
Money action_cost = _price[PR_TOWN_ACTION] * GetTownActionCost(this->sel_action) >> 8;
bool affordable = Company::IsValidID(_local_company) && action_cost < GetAvailableMoney(_local_company);
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.framerect),
GetString(this->action_tooltips[to_underlying(this->sel_action)], action_cost),
affordable ? TC_YELLOW : TC_RED);
}
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
switch (widget) {
@ -476,10 +344,6 @@ public:
}
break;
case WID_TV_SHOW_AUTHORITY: // town authority
ShowTownAuthorityWindow(this->window_number);
break;
case WID_TV_CHANGE_NAME: // rename
ShowQueryString(GetString(STR_TOWN_NAME, this->window_number), STR_TOWN_VIEW_RENAME_TOWN_BUTTON, MAX_LENGTH_TOWN_NAME_CHARS, this, CS_ALPHANUMERAL, {QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars});
break;
@ -503,14 +367,68 @@ public:
case WID_TV_DELETE: // delete town - only available on Scenario editor
Command<CMD_DELETE_TOWN>::Post(STR_ERROR_TOWN_CAN_T_DELETE, static_cast<TownID>(this->window_number));
break;
case WID_TV_ZONE: {
bool new_show_state = !this->town->show_zone;
TownID index = this->town->index;
new_show_state ? _town_local_authority_kdtree.Insert(index) : _town_local_authority_kdtree.Remove(index);
this->town->show_zone = new_show_state;
this->SetWidgetLoweredState(widget, new_show_state);
MarkWholeScreenDirty();
break;
}
case WID_TV_COMMAND_LIST: {
int y = this->GetRowFromWidget(pt.y, widget, WidgetDimensions::scaled.framerect.top, GetCharacterHeight(FS_NORMAL)) - 1;
auto action = this->enabled_actions.GetNthSetBit(y);
if (!action.has_value()) break;
this->sel_action = *action;
this->SetDirty();
/* When double-clicking, continue */
if (click_count == 1 || !this->available_actions.Test(this->sel_action)) break;
[[fallthrough]];
}
case WID_TV_EXECUTE:
Command<CMD_DO_TOWN_ACTION>::Post(STR_ERROR_CAN_T_DO_THIS, this->town->xy, static_cast<TownID>(this->window_number), this->sel_action);
break;
case WID_TV_PANE_INFO:
TownViewWindow::initial_visible_pane = this->visible_pane = 0;
this->ResizePanes();
break;
case WID_TV_PANE_RATINGS:
TownViewWindow::initial_visible_pane = this->visible_pane = 1;
this->ResizePanes();
break;
case WID_TV_PANE_ACTIONS:
TownViewWindow::initial_visible_pane = this->visible_pane = 2;
this->ResizePanes();
break;
}
}
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
{
switch (widget) {
case WID_TV_INFO:
size.height = GetDesiredInfoHeight(size.width) + padding.height;
case WID_TV_COMMAND_LIST:
if (this->visible_pane != 2) {
size.height = 0;
} else {
size.height = (to_underlying(TownAction::End) + 1) * GetCharacterHeight(FS_NORMAL) + padding.height;
size.width = GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTIONS_TITLE).width;
for (TownAction i = {}; i != TownAction::End; ++i) {
size.width = std::max(size.width, GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + to_underlying(i)).width + padding.width);
}
size.width += padding.width;
}
break;
}
}
@ -521,6 +439,7 @@ public:
*/
uint GetDesiredInfoHeight(int width) const
{
width -= WidgetDimensions::scaled.framerect.Horizontal();
uint aimed_height = static_cast<uint>(1 + CargoSpec::town_production_cargoes[TPE_PASSENGERS].size() + CargoSpec::town_production_cargoes[TPE_MAIL].size()) * GetCharacterHeight(FS_NORMAL);
bool first = true;
@ -540,23 +459,76 @@ public:
if (_settings_game.economy.station_noise_level) aimed_height += GetCharacterHeight(FS_NORMAL);
if (!this->town->text.empty()) {
aimed_height += GetStringHeight(this->town->text.GetDecodedString(), width - WidgetDimensions::scaled.framerect.Horizontal());
aimed_height += GetStringHeight(this->town->text.GetDecodedString(), width);
}
return aimed_height;
return aimed_height + WidgetDimensions::scaled.framerect.Vertical();
}
void ResizeWindowAsNeeded()
uint GetDesiredRatingHeight(int) const
{
const NWidgetBase *nwid_info = this->GetWidget<NWidgetBase>(WID_TV_INFO);
uint aimed_height = GetDesiredInfoHeight(nwid_info->current_x);
if (aimed_height > nwid_info->current_y || (aimed_height < nwid_info->current_y && nwid_info->current_y > nwid_info->smallest_y)) {
this->ReInit();
int lines = 1;
for (const Company *c : Company::Iterate()) {
if ((this->town->have_ratings.Test(c->index) || this->town->exclusivity == c->index)) {
++lines;
}
}
return this->rating_line_height * std::max(3, lines) + WidgetDimensions::scaled.framerect.Vertical();
}
uint GetDesiredActionInfoHeight(int width) const
{
width -= WidgetDimensions::scaled.framerect.Horizontal();
int height = 0;
for (TownAction i = {}; i != TownAction::End; ++i) {
Money price = _price[PR_TOWN_ACTION] * GetTownActionCost(i) >> 8;
height = std::max(height, GetStringHeight(GetString(this->action_tooltips[to_underlying(i)], price), width));
}
return height + WidgetDimensions::scaled.framerect.Vertical();
}
bool UpdatePaneSizes()
{
bool changed = false;
auto *sel = this->GetWidget<NWidgetStacked>(WID_TV_PANE_SEL);
if (sel != nullptr) {
if (auto *nwid = this->GetWidget<NWidgetCore>(WID_TV_INFO); nwid != nullptr) {
uint y = this->visible_pane == 0 ? GetDesiredInfoHeight(nwid->current_x) : 0;
changed |= nwid->UpdateVerticalSize(y);
}
if (auto *nwid = this->GetWidget<NWidgetCore>(WID_TV_RATING_INFO); nwid != nullptr) {
uint y = this->visible_pane == 1 ? GetDesiredRatingHeight(nwid->current_x) : 0;
changed |= nwid->UpdateVerticalSize(y);
}
if (auto *nwid = this->GetWidget<NWidgetCore>(WID_TV_ACTION_INFO); nwid != nullptr) {
uint y = this->visible_pane == 2 ? GetDesiredActionInfoHeight(nwid->current_x) : 0;
changed |= nwid->UpdateVerticalSize(y);
}
}
return changed;
}
void ResizePanes()
{
this->SetPaneState();
/* We want to resize the window while maintaining the size of the viewport. */
auto *nwid = this->GetWidget<NWidgetViewport>(WID_TV_VIEWPORT);
int old_y = static_cast<int>(nwid->current_y);
this->OnResize();
int new_y = static_cast<int>(nwid->current_y);
if (old_y != new_y) ResizeWindow(this, 0, old_y - new_y, false, false);
}
void OnResize() override
{
if (this->UpdatePaneSizes()) this->ReInit(0, 0);
if (this->viewport != nullptr) {
NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(WID_TV_VIEWPORT);
nvp->UpdateViewportCoordinates(this);
@ -573,6 +545,11 @@ public:
}
}
/** Redraw the whole window on a regular interval. */
const IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(3), [this](auto) {
this->SetDirty();
}};
/**
* Some data on this window has become invalid.
* @param data Information about the changed data.
@ -581,9 +558,16 @@ public:
void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
{
if (!gui_scope) return;
/* Called when setting station noise or required cargoes have changed, in order to resize the window */
this->enabled_actions = GetEnabledActions();
this->available_actions = GetMaskOfTownActions(_local_company, this->town);
if (!this->enabled_actions.Test(this->sel_action)) {
this->sel_action = TownAction::End;
}
this->SetDirty(); // refresh display for current size. This will allow to avoid glitches when downgrading
this->ResizeWindowAsNeeded();
this->ResizePanes();
}
void OnQueryTextFinished(std::optional<std::string> str) override
@ -614,10 +598,23 @@ static constexpr NWidgetPart _nested_town_game_view_widgets[] = {
NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_TV_VIEWPORT), SetMinimalSize(254, 86), SetFill(1, 0), SetResize(1, 1),
EndContainer(),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_INFO), SetMinimalSize(260, 32), SetResize(1, 0), SetFill(1, 0), EndContainer(),
NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize),
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TV_SHOW_AUTHORITY), SetMinimalSize(80, 12), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON, STR_TOWN_VIEW_LOCAL_AUTHORITY_TOOLTIP),
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TV_CATCHMENT), SetMinimalSize(40, 12), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_BUTTON_CATCHMENT, STR_TOOLTIP_CATCHMENT),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TV_PANE_INFO), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_INFO, STR_TOWN_VIEW_INFO_TOOLTIP),
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TV_PANE_RATINGS), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_RATINGS, STR_TOWN_VIEW_RATINGS_TOOLTIP),
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TV_PANE_ACTIONS), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_ACTIONS, STR_TOWN_VIEW_ACTIONS_TOOLTIP),
EndContainer(),
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_TV_PANE_SEL),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_INFO), SetResize(1, 0), SetFill(1, 1), EndContainer(),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_RATING_INFO), SetResize(1, 0), SetFill(1, 1), EndContainer(),
NWidget(NWID_VERTICAL),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_COMMAND_LIST), SetResize(1, 0), SetFill(1, 1), SetToolTip(STR_LOCAL_AUTHORITY_ACTIONS_TOOLTIP), EndContainer(),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_ACTION_INFO), SetResize(1, 0), SetFill(1, 0), EndContainer(),
EndContainer(),
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TV_EXECUTE), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_LOCAL_AUTHORITY_DO_IT_BUTTON, STR_LOCAL_AUTHORITY_DO_IT_TOOLTIP),
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TV_ZONE), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_LOCAL_AUTHORITY_ZONE, STR_LOCAL_AUTHORITY_ZONE_TOOLTIP),
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TV_CATCHMENT), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_BUTTON_CATCHMENT, STR_TOOLTIP_CATCHMENT),
NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
EndContainer(),
};

View File

@ -21,30 +21,27 @@ enum TownDirectoryWidgets : WidgetID {
WID_TD_WORLD_POPULATION, ///< The world's population.
};
/** Widgets of the #TownAuthorityWindow class. */
enum TownAuthorityWidgets : WidgetID {
WID_TA_CAPTION, ///< Caption of window.
WID_TA_ZONE_BUTTON, ///< Turn on/off showing local authority zone.
WID_TA_RATING_INFO, ///< Overview with ratings for each company.
WID_TA_COMMAND_LIST, ///< List of commands for the player.
WID_TA_SCROLLBAR, ///< Scrollbar of the list of commands.
WID_TA_ACTION_INFO, ///< Additional information about the action.
WID_TA_EXECUTE, ///< Do-it button.
};
/** Widgets of the #TownViewWindow class. */
enum TownViewWidgets : WidgetID {
WID_TV_CAPTION, ///< Caption of window.
WID_TV_VIEWPORT, ///< View of the center of the town.
WID_TV_INFO, ///< General information about the town.
WID_TV_CENTER_VIEW, ///< Center the main view on this town.
WID_TV_SHOW_AUTHORITY, ///< Show the town authority window.
WID_TV_CHANGE_NAME, ///< Change the name of this town.
WID_TV_CATCHMENT, ///< Toggle catchment area highlight.
WID_TV_EXPAND, ///< Expand this town (scenario editor only).
WID_TV_EXPAND_BUILDINGS, ///< Expand number of buildings this town (scenario editor only).
WID_TV_EXPAND_ROADS, ///< Expand roads of this town (scenario editor only).
WID_TV_DELETE, ///< Delete this town (scenario editor only).
WID_TV_PANE_SEL,
WID_TV_PANE_INFO,
WID_TV_PANE_RATINGS,
WID_TV_PANE_ACTIONS,
WID_TV_RATING_INFO, ///< Overview with ratings for each company.
WID_TV_COMMAND_LIST, ///< List of commands for the player.
WID_TV_ACTION_INFO, ///< Additional information about the action.
WID_TV_EXECUTE, ///< Do-it button.
WID_TV_ZONE, ///< Turn on/off showing local authority zone.
};
/** Widgets of the #FoundTownWindow class. */

View File

@ -189,12 +189,6 @@ enum WindowClass : uint16_t {
WC_TEXTFILE,
/**
* Town authority; %Window numbers:
* - #TownID = #TownAuthorityWidgets
*/
WC_TOWN_AUTHORITY,
/**
* Vehicle details; %Window numbers:
* - #VehicleID = #VehicleDetailsWidgets