- Дек
- 2
- 1
Пользователь
Что такое Pawn и зачем это нужно
Pawn — это простой язык для встраивания в игры/программы.- Где используется: В основном в модах для SA-MP (GTA San Andreas Multiplayer)
- Для чего: Чтобы делать свои сервера, скрипты, миссии
- Простота: Легче чем C++, но строже чем Python
Что будет в программе:
- Теория по частям — от переменных до создания команд
- Практика — пишешь код, проверяешь прямо в программе
- Примеры из реальных скриптов — как в настоящих модах
- Шпаргалки — чтобы не забыть синтаксис
1. Раздел "Основы"
1.1. Что такое переменные- Цифры: new score = 100;
- Текст: new nick[24] = "John";
- Дробные: Float:health = 100.0;
1.2. Вывод информации
- print("Привет мир!");
- printf("У %s %d HP", name, health);
1.3. Условия (if/else)
- if(money > 1000) { богатый; }
- if(admin == 1) { дать права; }
1.4. Циклы
- for(new i=0; i<10; i++) { }
2. Раздел "Команды для игроков"
2.1. Базовый шаблон командыpublic OnPlayerCommandText(playerid, cmdtext[])
{
if(strcmp(cmdtext, "/help", true) == 0)
{
SendClientMessage(playerid, цвет, "Помощь!");
return 1;
}
return 0;
}
2.2. Примеры команд:
- /me [действие]
- /givecash [ид] [сумма]
- /tp [x] [y] [z]
3. Раздел "Функции SA-MP"
3.1. Работа с игроком- GivePlayerMoney(playerid, money)
- SetPlayerPos(playerid, x, y, z)
- GetPlayerName(playerid, name, sizeof(name))
3.2. Сообщения
- SendClientMessage(playerid, цвет, текст)
- GameTextForAll(текст, время, стиль)
4. Раздел "Базы данных"
4.1. Сохранение статистики- Сохранить: деньги, уровень, опыт
- Загрузить при входе
- Обновить при выходе
4.2. Пример сохранения:
d_user_save[playerid] = 1; // флаг "нужно сохранить"
Как будем проверять код:
Простой валидатор (проверяльщик кода):
def check_pawn_task(user_code, task_number):"""Проверяем код ученика"""
# Задание 1: создать переменную
if task_number == 1:
if "new level = 1" in user_code or "new level=1" in user_code:
return "
elif "level = 1" in user_code:
return "
else:
return "
# Задание 2: простая команда
elif task_number == 2:
if "/help" in user_code and "SendClientMessage" in user_code:
return "
else:
return "
Реальные примеры из скриптов:
Пример 1: Команда /me (ролеплей)
if(strcmp(cmd, "/me", true) == 0){
new action[128];
if(!sscanf(params, "s[128]", action))
{
new str[144], name[MAX_PLAYER_NAME];
GetPlayerName(playerid, name, sizeof(name));
format(str, sizeof(str), "* %s %s", name, action);
SendClientMessageToAll(0xC2A2DAAA, str);
return 1;
}
return SendClientMessage(playerid, 0xFF0000AA, "Использование: /me [действие]");
}
Что вы сможете сделать после урока:
- Поймёт структуру Pawn скрипта
- Создаст свои переменные
- Напишет первую команду /help
- Сделает систему денег /givemoney
- Добавит телепорт /tp
- Создаст ролеплей команды /me, /do
- Привяжет данные к базе
- Сделает авторизацию (/login, /register)
- Сохранит прогресс игрока
- Соберёт всё в один мод
- Протестирует на локальном сервере
- Исправит баги и ошибки
Стартовый код программы (начало):
import tkinter as tkfrom tkinter import ttk, scrolledtext
import os
class PawnLearner:
def __init__(self):
self.window = tk.Tk()
self.window.title("PawnLearner - учим скрипты для SA-MP")
self.window.geometry("900x600")
# Текущий урок
self.current_lesson = 1
self.total_lessons = 10
# Создаем интерфейс
self.create_menu()
self.create_main_area()
self.create_sidebar()
def create_menu(self):
"""Верхнее меню"""
menubar = tk.Menu(self.window)
# Меню Файл
file_menu = tk.Menu(menubar, tearoff=0)
file_menu.add_command(label="Открыть пример", command=self.open_example)
file_menu.add_command(label="Сохранить код", command=self.save_code)
file_menu.add_separator()
file_menu.add_command(label="Выход", command=self.window.quit)
menubar.add_cascade(label="Файл", menu=file_menu)
# Меню Уроки
lessons_menu = tk.Menu(menubar, tearoff=0)
lessons_menu.add_command(label="1. Переменные", command=lambda: self.load_lesson(1))
lessons_menu.add_command(label="2. Команды", command=lambda: self.load_lesson(2))
lessons_menu.add_command(label="3. Функции SA-MP", command=lambda: self.load_lesson(3))
menubar.add_cascade(label="Уроки", menu=lessons_menu)
self.window.config(menu=menubar)
def create_main_area(self):
"""Основная область - теория и редактор"""
# Левая панель - теория
theory_frame = ttk.LabelFrame(self.window, text="Теория", padding=10)
theory_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5)
self.theory_text = scrolledtext.ScrolledText(theory_frame, wrap=tk.WORD, width=40)
self.theory_text.pack(fill=tk.BOTH, expand=True)
# Загружаем первый урок
self.load_lesson(1)
# Правая панель - практика
practice_frame = ttk.LabelFrame(self.window, text="Практика", padding=10)
practice_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5, pady=5)
# Задание
ttk.Label(practice_frame, text="Задание:").pack(anchor=tk.W)
self.task_label = ttk.Label(practice_frame, text="Создай переменную: new money = 1000;")
self.task_label.pack(anchor=tk.W, pady=(0, 10))
# Редактор кода
ttk.Label(practice_frame, text="Твой код:").pack(anchor=tk.W)
self.code_editor = scrolledtext.ScrolledText(practice_frame, height=15, wrap=tk.WORD)
self.code_editor.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
# Кнопки
btn_frame = ttk.Frame(practice_frame)
btn_frame.pack(fill=tk.X, pady=5)
ttk.Button(btn_frame, text="Проверить", command=self.check_code).pack(side=tk.LEFT, padx=2)
ttk.Button(btn_frame, text="Очистить", command=self.clear_code).pack(side=tk.LEFT, padx=2)
ttk.Button(btn_frame, text="Подсказка", command=self.show_hint).pack(side=tk.LEFT, padx=2)
# Результат
ttk.Label(practice_frame, text="Результат:").pack(anchor=tk.W)
self.result_text = tk.Text(practice_frame, height=4, bg="#f0f0f0")
self.result_text.pack(fill=tk.X, pady=(0, 10))
def create_sidebar(self):
"""Боковая панель - прогресс"""
sidebar = ttk.Frame(self.window, width=200)
sidebar.pack(side=tk.RIGHT, fill=tk.Y, padx=5, pady=5)
ttk.Label(sidebar, text="Твой прогресс:", font=('Arial', 12, 'bold')).pack(pady=10)
# Прогресс бар
self.progress_bar = ttk.Progressbar(sidebar, length=180, maximum=100)
self.progress_bar.pack(pady=10)
# Быстрые ссылки
ttk.Label(sidebar, text="Шпаргалки:").pack(anchor=tk.W, pady=(20,5))
links = [
"Синтаксис Pawn",
"Функции SA-MP",
"Цвета сообщений",
"Примеры команд"
]
for link in links:
btn = ttk.Button(sidebar, text=link, width=20,
command=lambda l=link: self.open_cheatsheet(l))
btn.pack(pady=2)
def load_lesson(self, lesson_num):
"""Загружаем урок из файла"""
self.current_lesson = lesson_num
# Простой пример урока
lessons = {
1: """
Переменная - это "коробка" для хранения данных.
Цифры:
new money = 1000;
new score = 0;
Текст (массив символов):
new name[24] = "Player";
new msg[128] = "Привет!";
Дробные числа (Float):
Float:health = 100.0;
Float
ВАЖНО: Все строки в Pawn - это массивы!
new text[размер] = "текст";""",
2: """
Команда в SA-MP - это то, что игрок пишет в чат.
Шаблон команды:
public OnPlayerCommandText(playerid, cmdtext[])
{
if(strcmp(cmdtext, "/help", true) == 0)
{
SendClientMessage(playerid, 0x00FF00AA, "Помощь!");
return 1;
}
return 0;
}
Разбор:
- strcmp - сравнение строк
- "/help" - текст команды
- true - игнорировать регистр
- SendClientMessage - отправить сообщение
- return 1 - команда обработана
- return 0 - команда не найдена"""
}
if lesson_num in lessons:
self.theory_text.delete(1.0, tk.END)
self.theory_text.insert(1.0, lessons[lesson_num])
# Меняем задание
if lesson_num == 1:
self.task_label.config(text="Задание: Создай переменную: new level = 1;")
elif lesson_num == 2:
self.task_label.config(text="Задание: Создай команду /hello")
def check_code(self):
"""Проверяем код пользователя"""
code = self.code_editor.get(1.0, tk.END).strip()
if self.current_lesson == 1:
# Проверяем создание переменной
if "new level = 1" in code or "new level=1" in code:
self.show_result("
self.update_progress(10) # +10% к прогрессу
elif "level = 1" in code:
self.show_result("
else:
self.show_result("
elif self.current_lesson == 2:
# Проверяем создание команды
if "/hello" in code and "SendClientMessage" in code:
self.show_result("
self.update_progress(10)
else:
self.show_result("
def show_result(self, text):
"""Показываем результат проверки"""
self.result_text.delete(1.0, tk.END)
self.result_text.insert(1.0, text)
def clear_code(self):
"""Очищаем редактор"""
self.code_editor.delete(1.0, tk.END)
def show_hint(self):
"""Показываем подсказку"""
hints = {
1: "
2: "
}
if self.current_lesson in hints:
self.show_result(hints[self.current_lesson])
def update_progress(self, points):
"""Обновляем прогресс бар"""
current = self.progress_bar['value']
self.progress_bar['value'] = min(current + points, 100)
def open_example(self):
"""Открываем пример кода"""
# Простые примеры
examples = {
"Команда /me": """
public OnPlayerCommandText(playerid, cmdtext[])
{
if(strcmp(cmdtext, "/me", true) == 0)
{
new action[128];
if(sscanf(params, "s[128]", action))
return SendClientMessage(playerid, 0xFF0000AA, "Используй: /me [действие]");
new str[144], name[MAX_PLAYER_NAME];
GetPlayerName(playerid, name, sizeof(name));
format(str, sizeof(str), "* %s %s", name, action);
SendClientMessageToAll(0xC2A2DAAA, str);
return 1;
}
return 0;
}""",
"Сохранение денег": """
// При выходе игрока
public OnPlayerDisconnect(playerid, reason)
{
new money = GetPlayerMoney(playerid);
// Сохраняем в файл (пример)
new file_name[64], str[16];
GetPlayerName(playerid, file_name, sizeof(file_name));
format(file_name, sizeof(file_name), "players/%s.ini", file_name);
format(str, sizeof(str), "%d", money);
dini_Set(file_name, "Money", str);
return 1;
}"""
}
# Показываем выбор
self.show_result("
def open_cheatsheet(self, topic):
"""Открываем шпаргалку"""
cheats = {
"Синтаксис Pawn": """
new var = значение; // Число
new text[размер]; // Строка
Float:decimal = 1.5; // Дробное
if(условие) { код; } // Условие
for(new i=0; i<10; i++) // Цикл
printf("Текст %s", var); // Вывод""",
"Цвета сообщений": """
0xFF0000AA - Красный
0x00FF00AA - Зеленый
0x0000FFAA - Синий
0xFFFF00AA - Желтый
0xFFFFFFAA - Белый
0xC2A2DAAA - Ролеплей"""
}
if topic in cheats:
self.show_result(f"
def save_code(self):
"""Сохраняем код в файл"""
code = self.code_editor.get(1.0, tk.END)
with open("my_script.pwn", "w", encoding="utf-8") as f:
f.write(code)
self.show_result("
def run(self):
"""Запуск программы"""
self.window.mainloop()
# Запускаем программу
if __name__ == "__main__":
app = PawnLearner()
app.run()