S.T.A.L.K.E.R.: Call of Pripyat "MapEditor"

Данная утилита предназначена для получения координат наложения миникарты на глобальную карту в PDA (персональных цифровых помощниках, или КПК).

Для работы с программой необходимо выполнить следующие шаги:

  1. Загрузка текстур: При запуске утилиты загрузите глобальную и локальную текстуры, которые будут использует для наложения миникарты.
  2. Перемещение миникарты: С помощью левого клика мыши, а также специализированных кнопок интерфейса, вы сможете переместить миникарту в нужное положение относительно глобальной карты.
  3. После того как миникарта будет правильно расположена, соответствующие координаты необходимо внести в файл `game_maps_single.ltx`.

Следует отметить, что программа теоретически совместима с файлами всех частей трилогии. Для этого вам потребуется загрузить глобальную карту, соответствующую конкретной части игры. Убедитесь, что все необходимые файлы готовы и правильно загружены для оптимального использования утилиты.

Исходный код:

Спойлер

import tkinter as tk

from tkinter import filedialog, messagebox

from PIL import Image, ImageTk

import os

class TextureEditor:

def __init__(self, master):

self.master = master

self.master.title("Game Maps Single Editor")

# Всплывающее окно с инструкцией

self.show_instructions()

# Загрузка первой текстуры

self.texture1_path = self.select_texture_file(title="Выберите первую текстуру", required_name="ui_global_map.dds", extensions=[('DDS files', '*.dds')])

if self.texture1_path:

self.texture1 = Image.open(self.texture1_path)

else:

return

# Загрузка второй текстуры

self.texture2_path = self.select_texture_file(title="Выберите вторую текстуру", extensions=[('DDS files', '*.dds')])

if self.texture2_path:

self.texture2 = Image.open(self.texture2_path).resize((250, 250), Image.LANCZOS)

else:

return

# Устанавливаем фиксированную ширину и изменяемую высоту окна

self.fixed_width = self.texture1.width

self.master.geometry(f"{self.fixed_width}x{self.texture1.height}")

self.master.resizable(False, True)

# Создаем Canvas

self.canvas = tk.Canvas(master, bg="white", height=self.texture1.height)

self.canvas.pack(fill=tk.BOTH, expand=True)

# Отображаем первую текстуру

self.tk_texture1 = ImageTk.PhotoImage(self.texture1)

self.canvas.create_image(0, 0, image=self.tk_texture1, anchor=tk.NW)

# Отображаем вторую текстуру

self.tk_texture2 = ImageTk.PhotoImage(self.texture2)

self.texture2_coords = (0, 0)

self.texture2_id = self.canvas.create_image(self.texture2_coords[0], self.texture2_coords[1],

image=self.tk_texture2, anchor=tk.NW)

# Обновляем Canvas

self.update_canvas()

# Привязываем события мыши

self.canvas.bind("<Button-1>", self.start_move_texture2)

self.canvas.bind("<B1-Motion>", self.move_texture2)

self.canvas.bind("<ButtonRelease-1>", self.release_mouse)

# Обработка перемещения мыши для скрытия или отображения курсора

self.canvas.bind("<Motion>", self.check_cursor_visibility)

# Колесико мыши для прокрутки

self.canvas.bind("<MouseWheel>", self.on_mouse_wheel)

# Создание фрейма для кнопок

self.button_frame = tk.Frame(master, bg="lightgray")

self.button_frame.place(x=0, y=0, relwidth=1)

self.save_button = tk.Button(self.button_frame, text="global_rect", command=self.save_coordinates, bg="gray", width=18)

self.save_button.pack(side=tk.LEFT, padx=5, pady=5)

self.increase_button = tk.Button(self.button_frame, text="+", command=self.increase_texture2, width=5, bg="lightgray")

self.increase_button.pack(side=tk.LEFT, padx=5, pady=5)

self.decrease_button = tk.Button(self.button_frame, text="-", command=self.decrease_texture2, width=5, bg="lightgray")

self.decrease_button.pack(side=tk.LEFT, padx=5, pady=5)

# Обновляем область прокрутки

self.update_scroll_region()

def show_instructions(self):

messagebox.showinfo("Инструкции", "Управление программой:\n\n"

"- Первой нужно выбирать текстуру глобальной карты (ui_global_map).\n"

"- Второй - локальной карты (map).\n"

"- Текстуру map.dds возможно перезаписывать на нужную.\n"

"- Левый клик для перемещения текстуры карты.\n"

"- Перетаскивайте текстуру с помочью левой кнопки мыши.\n"

"- Используйте кнопки увеличения (+) и уменьшения (-) для изменения размера текстуры.\n"

"- Используйте колесико мыши, для просмотра глобальной карты.\n"

"- Кнопка 'global_rect' сохраняет координаты текстуры в файл (coordinates.txt).\n",

icon='info')

def select_texture_file(self, title, required_name=None, extensions=None):

while True:

file_path = filedialog.askopenfilename(title=title, filetypes=extensions)

if not file_path: # Проверяем, если пользователь отменил выбор

return None

if required_name:

if os.path.basename(file_path) == required_name:

return file_path

else:

messagebox.showerror("Ошибка", f"Выберите файл с именем '{required_name}'!")

else:

if file_path.lower().endswith('.dds'):

return file_path

else:

messagebox.showerror("Ошибка", "Выберите файл в формате DDS!")

def update_canvas(self):

self.canvas.delete("all") # Удаляем все

self.canvas.create_image(0, 0, image=self.tk_texture1, anchor=tk.NW)

self.canvas.create_image(self.texture2_coords[0], self.texture2_coords[1],

image=self.tk_texture2, anchor=tk.NW)

self.update_scroll_region()

def update_scroll_region(self):

self.canvas.configure(scrollregion=self.canvas.bbox("all"))

def start_move_texture2(self, event):

if (self.texture2_coords[0] <= event.x <= self.texture2_coords[0] + self.texture2.width and

self.texture2_coords[1] <= event.y <= self.texture2_coords[1] + self.texture2.height):

self.texture2_coords = (event.x, event.y)

self.master.config(cursor="none")

def move_texture2(self, event):

new_x = event.x

new_y = event.y

# Ограничиваем новые координаты

if new_x < 0:

new_x = 0

elif new_x + self.texture2.width > self.texture1.width:

new_x = self.texture1.width - self.texture2.width

if new_y < 0:

new_y = 0

elif new_y + self.texture2.height > self.texture1.height:

new_y = self.texture1.height - self.texture2.height

self.texture2_coords = (new_x, new_y)

self.update_canvas()

def release_mouse(self, event):

self.master.config(cursor="")

def check_cursor_visibility(self, event):

# Проверка, нужно ли скрыть курсор

if (self.texture2_coords[0] <= event.x <= self.texture2_coords[0] + self.texture2.width and

self.texture2_coords[1] <= event.y <= self.texture2_coords[1] + self.texture2.height):

self.master.config(cursor="none")

else:

self.master.config(cursor="")

def on_mouse_wheel(self, event):

# Прокрутка с помощью колесика мыши

self.canvas.yview_scroll(-1 * (event.delta // 120), "units")

def increase_texture2(self):

delta = 10 # Размер увеличения

new_width = self.texture2.width + delta

new_height = self.texture2.height + delta

self.texture2 = self.texture2.resize((new_width, new_height), Image.LANCZOS)

self.tk_texture2 = ImageTk.PhotoImage(self.texture2) # Обновляем отображаемое изображение

self.update_canvas()

def decrease_texture2(self):

delta = 10 # Размер уменьшения

new_width = max(1, self.texture2.width - delta)

new_height = max(1, self.texture2.height - delta)

self.texture2 = self.texture2.resize((new_width, new_height), Image.LANCZOS)

self.tk_texture2 = ImageTk.PhotoImage(self.texture2) # Обновляем отображаемое изображение

self.update_canvas()

def save_coordinates(self):

x1, y1 = self.texture2_coords

x2, y2 = x1 + self.texture2.width, y1 + self.texture2.height

coords = f"{x1:.1f},{y1:.1f},{x2:.1f},{y2:.1f}"

with open("coordinates.txt", "w") as file:

file.write(f"global_rect = {coords}\n")

print(f"Сохраненные координаты: global_rect = {coords}")

# Запуск приложения

if __name__ == "__main__":

root = tk.Tk()

app = TextureEditor(root)

root.mainloop()

Инструкция по установке:

  1. Скачайте файл;
  2. Распаковать в удобное место;
  3. Использовать по назначению.

Автор: Dont Name

5
1
Комментарии: 1
Ваш комментарий

Программка работает нормально. Объяснение: "Как работать с прожкой" - кривое. Зачет. Для пристрелки расположения локации пойдёт. Но для сборки общей карты с локациями лучше использовать "Map dragger" - программа сложная, но позволяет расположить сразу все карты локаций на общей карте, относительно друг друга и подогнать размеры. Получить координаты как расположения карты локации так и размеры самой карты локации.