PDA

Просмотр полной версии : [Мануал] Система домов для самых маленьких



Seviel
01.01.2017, 20:04
Доброго времени суток дамы и господа.
Сегодня я покажу как реализовать простенькую систему домов. UPD: 04.01.2017
Как будет работать
При запуске сервера будет загружаться две таблицы, в одной будет хранится информация о доме(нашем случае id, координаты входа, интерьер и владелец), а вторая таблица будет хранить информацию о интерьере(id, координаты выхода, интерьер, название). Сначала будет загружаться таблица с интерьерами, а после таблица с домами. В таблице с домами есть поле интерьер, в этом поле хранится id из таблицы с интерьерами.
Что нам нужно
А нужно нам 3 инклуда(с плагинами):

#include <a_samp>
#include <a_mysql> // - У меня R39-2
#include <dc_cmd>
mysql: https://github.com/pBlueG/SA-MP-MySQL/releases
dc_cmd: http://pro-pawn.ru/showthread.php?1028-DC_CMD-v2-8-(23-03-14)
Поля в таблице
Таблица с домами имеет следующие поля:


id
integer
AUTO_INCREMENT


X
double



Y
double



Z
double



interior
integer(11)



owner
varchar(24)



а таблица с интерьерами


id
integer
AUTO_INCREMENT


X
double



Y
double



Z
double



interior
integer(11)



caption
varchar(64)



Заполненную таблицу с интерьерами вы можете скачать здесь (https://www.dropbox.com/s/djrdvi1scldmzmk/interiors.sql?dl=0)(не все интерьеры)
Переменные и константы


#define MAX_HOUSES 200 // - Максимальное количество домов.
#define MAX_INTERIORS 20 // - Максимальное количество интерьеров
new connection; // - id подключения к базе данных.
enum hInfo
{
id, // - id дома
Float:enterX, // - координаты входа
Float:enterY,
Float:enterZ,
interior, // - Интерьер
owner[25] // - Владелец
}
new House[MAX_HOUSES][hInfo]; // - Массив со всеми домами.
enum iInfo
{
id, // - id интерьера
Float:enterX, // - координаты входа
Float:enterY,
Float:enterZ,
interior, // - Интерьер
caption[65] // - Название
}
new Int[MAX_HOUSES][iInfo];
new Houses, Ints; // - Переменные хранящие количество домов
new housePickupX, housePickupY, housePickupZ; // - Переменные хранящие позицию входа при созданий дома

Подключение к базе данных и загрузка таблиц
Перейдем к OnGameModeInit()

connection = mysql_connect(const host[], const user[], const database[], const password[]);
const host[]: IP, на котором расположена База Данных
const user[]: логин пользователя для доступа к Базе Данных
const database[]: имя Базы Данных
const password[]: пароль, для подключения к Базе Данных


mysql_function_query(connection, "SELECT * FROM `interiors`", true, "LoadInts", "");
mysql_function_query(connection, "SELECT * FROM `houses`", true, "LoadHouses", "");

houses и interiors - это таблицы
LoadHouses и LoadInts - это паблики для обработки.
Добавьте его конец мода.


forward LoadInts();
public LoadInts()
{
new row1, row2;
cache_get_data(row1, row2);
if(row1)
{
for(new i; i < row1; i++) // перебираем каждую строку из выборки
{
Int[i][id] = cache_get_field_content_int(i, "id"); // переносим данные из бд в массив
Int[i][enterX] = cache_get_field_content_float(i, "X");
Int[i][enterY] = cache_get_field_content_float(i, "Y");
Int[i][enterZ] = cache_get_field_content_float(i, "Z");
Int[i][interior] = cache_get_field_content_int(i, "interior");
cache_get_field_content(i, "owner", Int[i][caption], connect_mysql, 64);
Ints++; // увеличиваем значение переменной при каждой итерации
}
printf("Загружено интерьеров: %d", Ints); // выводим в консоль сколько домов было загружено
}
else
{
print("Интерьеры не были загружены!"); // выводим в консоль ошибку
}
return true;
}
forward LoadHouses();
public LoadHouses()
{
new row1, row2;
cache_get_data(row1, row2);
if(row1)
{
for(new i; i < row1; i++) // перебираем каждую строку из выборки
{
House[i][id] = cache_get_field_content_int(i, "id"); // переносим данные из бд в массив
House[i][enterX] = cache_get_field_content_float(i, "X");
House[i][enterY] = cache_get_field_content_float(i, "Y");
House[i][enterZ] = cache_get_field_content_float(i, "Z");
House[i][interior] = cache_get_field_content_int(i, "interior");
cache_get_field_content(i, "owner", House[i][owner], connect_mysql, 24);
CreateDynamicPickup(19132, 23, House[i][enterX], House[i][enterY], House[i][enterZ], -1); // создаем пикап входа
new h = House[i][interior];
CreateDynamicPickup(19132, 23, Int[h][enterX], Int[h][enterY], Int[h][enterZ], -1); // создаем пикап выхода
Houses++; // увеличиваем значение переменной при каждой итерации
}
printf("Загружено домов: %d", Houses); // выводим в консоль сколько домов было загружено
}
else
{
print("Дома не были загружены!"); // выводим в консоль ошибку
}
return true;
}

Делаем вход и выход
В OnPlayerKeyStateChange добавляем:

if(newkeys == KEY_WALK) // проверяем нажатие кнопки
{
for(new i; i != Houses; i++)
{
new h = House[i][interior];
if(IsPlayerInRangeOfPoint(playerid, 1.0, House[i][enterX], House[i][enterY], House[i][enterZ])) //проверка расстояния к пикапу входа
{
SetPlayerPos(playerid, Int[h][enterX], Int[h][enterY], Int[h][enterZ]); // отправляем игрока на пикап выхода
SetPlayerInterior(playerid, Int[h][interior]); // устанавливаем игроку интерьер
SetPlayerVirtualWorld(playerid, House[i][id]); // Чтобы один интерьер можно было использовать для нескольких домов
break; // Выходим из цикла
}
if(IsPlayerInRangeOfPoint(playerid, 1.0, Int[h][enterX], Int[h][enterY], Int[h][enterZ])) // проверка на расстояние к пикапу выхода
{
SetPlayerPos(playerid, House[i][enterX], House[i][enterY], House[i][enterZ]); // отправляем на пикап входа
SetPlayerInterior(playerid, 0); // устанавливаем 0 интерьер игроку
SetPlayerVirtualWorld(playerid, 0); // возвращаем игрока в 0 виртуальный мир
break;
}
}
}
Делаем команду добавления дома
Команда по добавлению домов, состоит из двух частей. Первая устанавливает точку входа, второя выбирает интерьер.
В конец мода:


CMD:addhouse(playerid)
{
if(/*ваша проверка на админки*/) < 5) return true;
GetPlayerPos(playerid, housePickupX, housePickupY, housePickupZ); // получаем координаты игрока
SetPVarInt(playerid, "addHouse", 1); // создаем PVar
SendClientMessage(playerid, -1, "Вы установили точку входа, выберите интерьер из списка");
for(new i; i < Interior; i++)
{
strcat(string, Int[i][iCaption]);
strcat(string, "\n");
}
SPD(playerid, 8, DSL, "Интерьеры", string, "Выбрать", "Выход");
return true;
}
и в OnDialogResponse делаем восьмой диалог(у меня switch поэтому case, если у вас на if то замените case 8: на if(dialogid == 8))


case 8:
{
if(!response) return true;
static new_str[] = "INSERT INTO `houses` (`id`,`X`,`Y`,`Z`,`interior`,`owner`) VALUES (NULL,'%f','%f','%f','%d','%s')";
new string[sizeof(new_str)+MAX_PLAYER_NAME+62];
GetPlayerName(playerid, string, sizeof(string)); // Получаем имя игрока
mysql_format(connect_mysql, string, sizeof(string), new_str, housePickupX, housePickupY, housePickupZ, listitem, string);
mysql_function_query(connect_mysql, string, false, "", "");
SCM(playerid, -1, "Вы создали дом!");
}

Вывод
Я показал пример, как по мне хороший, а вы как хотите так и делайте. Не нравится напишите, нравится напишите.

Wise
01.01.2017, 20:28
Урок предусматривает разъяснение всех функций. Что, куда, зачем?
А у тебя получился обычный мануал. Пихаем туда, пихаем сюда...

Seviel
01.01.2017, 20:31
Урок предусматривает разъяснение всех функций. Что, куда, зачем?
А у тебя получился обычный мануал. Пихаем туда, пихаем сюда...

Да с разделом я накосячил, когда начинал писать думал буду разъяснять, но потом лень стало.

middlematt
02.01.2017, 01:10
Версию MySQL хотя-бы указал

HarrWe
02.01.2017, 14:58
100% есть баг, что когда ты выходишь из инта тебя спавнит не у входа в дом, а в последнем доме к которому принадлежит данный инт, поэтому нужно проверять при выходе ID дома.

Seviel
02.01.2017, 16:38
Версию MySQL хотя-бы указал
Хорошо укажу.

100% есть баг, что когда ты выходишь из инта тебя спавнит не у входа в дом, а в последнем доме к которому принадлежит данный инт, поэтому нужно проверять при выходе ID дома.
Вы проверяли?

Skyline
03.01.2017, 03:53
Ну как то не впечатлило. Начал хорошо....

123
03.01.2017, 06:43
Версия MySQL указана R41-2, хотя в коде используются R39. Ясно, понятно..