PDA

Просмотр полной версии : [Вопрос] Динамические пикапы



Kovshevoy
01.11.2018, 22:53
Ух, как же я люблю делать динамические системы, а потом бомбить почему оно не работает.

Добрый вечер, джентельмены, уже хрен знает сколько времени пытаюсь сделать динамическую систему пикапов, но вечно выходит какой-то казус. То оно все работает, создается пикап - но не телепортирует когда использую клавишу, то не создает пикап. Я в отчаянии и прошу Вашей помощи, ибо по-другому скорей всего пробью себе череп чем-то острым, или мой ноутбук попадет в гроб для железок.

Собственно, паблики загрузки/создания/обновления и команды для создания/удаления/редактирования


new ENTER_COUNT = 0;
const MAX_ENTER_NAME = 32;
const MAX_ENTERS = 500;

enum enters_headers
{
e_id,
e_name[MAX_ENTER_NAME],
Float:e_coordX,
Float:e_coordY,
Float:e_coordZ,
Float:e_coordA,
Float:e_int_coordX,
Float:e_int_coordY,
Float:e_int_coordZ,
Float:e_int_coordA,
e_exterior_vw,
e_exterior_int,
e_interior,
e_virtual_world,
e_pickup,
e_locked,
e_model,
e_author
};
new enter_sys[MAX_ENTERS][enters_headers];

stock MySQL_Enter_SaveInt(enterid, const row[], const int)
{
static query[45 - 6 + 25 + 11 + 1];
format(query,sizeof(query),"UPDATE `enters` SET `%s` = '%i' WHERE id = '%i'",
row,
int,
enter_sys[enterid][id]);
mysql_query(mysql_connect_id, query, false);
}

stock MySQL_Enter_SaveFloat(enterid, const row[], const Float:int)
{
static query[45 - 6 + 25 + 11 + 1];
format(query,sizeof(query),"UPDATE `enters` SET `%s` = '%f' WHERE id = '%i'",
row,
int,
enter_sys[enterid][id]);
mysql_query(mysql_connect_id, query, false);
}

stock MySQL_Enter_SaveString(enterid, const row[], const text[])
{
static query[45 - 6 + 25 + 128 + 1];
format(query,sizeof(query),"UPDATE `enters` SET `%s` = '%s' WHERE id = '%i'",
row,
text,
enter_sys[enterid][id]);
mysql_query(mysql_connect_id, query, false);
}
void EnterLoad_CallBack()
{
new i = 0;
cache_get_row_count(ENTER_COUNT);

if(ENTER_COUNT > MAX_ENTERS){
print("[Enters_System]: Предупреждение. Увеличьте размер MAX_ENTERS, чтобы система могла загрузить все данные с БД.");
return 1;
}

while(ENTER_COUNT > 0)
{
cache_get_value_index_int(i, 0, enter_sys[i][e_id]);
cache_get_value_index(i, 1, enter_sys[i][e_name]);
cache_get_value_index_float(i, 2, enter_sys[i][e_coordX]);
cache_get_value_index_float(i, 3, enter_sys[i][e_coordY]);
cache_get_value_index_float(i, 4, enter_sys[i][e_coordZ]);
cache_get_value_index_float(i, 5, enter_sys[i][e_coordA]);
cache_get_value_index_float(i, 6, enter_sys[i][e_int_coordX]);
cache_get_value_index_float(i, 7, enter_sys[i][e_int_coordY]);
cache_get_value_index_float(i, 8, enter_sys[i][e_int_coordZ]);
cache_get_value_index_float(i, 9, enter_sys[i][e_int_coordA]);
cache_get_value_index_int(i, 10, enter_sys[i][e_exterior_int]);
cache_get_value_index_int(i, 11, enter_sys[i][e_exterior_vw]);
cache_get_value_index_int(i, 12, enter_sys[i][e_interior]);
cache_get_value_index_int(i, 13, enter_sys[i][e_virtual_world]);
cache_get_value_index_int(i, 14, enter_sys[i][e_locked]);
cache_get_value_index_int(i, 15, enter_sys[i][e_model]);
Enter_Refresh(i);
i++;
}
printf("[Enters_System]: Загружено. Всего динамических пикапов: %i", ENTER_COUNT);
return 1;
}
void Enter_Create(playerid, enter_model, const enter_name[])
{
if(ENTER_COUNT > MAX_ENTERS)
{
SCM(playerid,-1,!""Error" Для того чтобы создать пикап, вам необходимо увеличить константу MAX_ENTERS!");
return 1;
}

ENTER_COUNT++;

static
enteradd_query[264 + MAX_ENTER_NAME + 8 + 8 + 8 + 8 + MAX_PLAYER_NAME + 2 + 10 + 5 + 1],
Float:point_x,
Float:point_y,
Float:point_z,
Float:point_a;

GetPlayerPos(playerid, point_x, point_y, point_z);
GetPlayerFacingAngle(playerid, point_a);
mysql_format(
mysql_connect_id,
enteradd_query,
sizeof(enteradd_query),
"INSERT INTO `enters` ( \
`id`, `e_model`, `e_name`, \
`e_coordX`, `e_coordY`, `e_coordZ`, `e_coordA`, \
`e_exterior_vw`, `e_exterior_int`, \
`author` \
) \
VALUES (\
'%i', '%i', '%e', \
'%.4f', '%.4f', '%.4f', '%.4f', \
'%i', '%i',\
'%e')",
ENTER_COUNT, enter_model, enter_name,
point_x, point_y, point_z, point_a,
GetPlayerVirtualWorld(playerid), GetPlayerInterior(playerid),
player[playerid][pName]
);
new Cache: addenter_cache = mysql_query(mysql_connect_id, enteradd_query);

if(cache_is_valid(addenter_cache))
{
SendClientMessage(playerid, -1, ""Notice"Вы успешно создали пикап!");
printf("[Enters_System]: %s создал пикап на координатах %.2f, %.2f, %.2f, %.2f| Название: %s | Модель пикапа: %i| ID: %i |",
player[playerid][pName],
point_x, point_y, point_z, point_a,
enter_name,
enter_model,
ENTER_COUNT
);

Enter_Refresh(ENTER_COUNT - 1);

/* enter_sys[ENTER_COUNT - 1][id] = ENTER_COUNT - 1;
enter_sys[ENTER_COUNT - 1][e_coord_x] = point_x;
enter_sys[ENTER_COUNT - 1][e_coord_y] = point_y;
enter_sys[ENTER_COUNT - 1][e_coord_z] = point_z;
enter_sys[ENTER_COUNT - 1][e_coord_a] = point_a;
strcat(enter_sys[ENTER_COUNT - 1][e_name], enter_name);
enter_sys[ENTER_COUNT - 1][e_model] = enter_model;*/
}
cache_delete(addenter_cache);
return 1;
}
void Enter_Refresh(enterid)
{
if (enterid != -1)
{
if (IsValidDynamicPickup(enter_sys[enterid][e_pickup])) DestroyDynamicPickup(enter_sys[enterid][e_pickup]);

enter_sys[enterid][e_pickup] = CreateDynamicPickup(19197, 23, enter_sys[enterid][e_coordX], enter_sys[enterid][e_coordY], enter_sys[enterid][e_coordZ], enter_sys[enterid][e_exterior_vw]);
}
return 1;
}
void Enter_Delete(playerid, enterid)
{
new enterdel_query[36+11+1],
result,
Cache: delenter_cache;

mysql_format(
mysql_connect_id,
enterdel_query,
sizeof(enterdel_query),
"DELETE FROM enters WHERE id = %i",
enterid
);

delenter_cache = mysql_query(mysql_connect_id, enterdel_query);
cache_get_result_count(result);
if(result)
{
SCM(playerid, -1, ""Notice"Пикап был удален.");
printf("[Enter System]: Пикап был удален.");

//if (IsValidDynamic3DTextLabel(enter_sys[enterid][h_text])) DestroyDynamic3DTextLabel(enter_sys[enterid][h_text]);
if (IsValidDynamicPickup(enter_sys[enterid][e_pickup])) DestroyDynamicPickup(enter_sys[enterid][e_pickup]);
}
else
{
SCM(playerid, -1, ""Error"Пикап не найден.");
printf("[Enter System]: Пикап не найден.");
}
cache_delete(delenter_cache);
return 1;
}
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
if (PRESSED(KEY_WALK)) {
for(new i = 0; i < ENTER_COUNT; i++) {
if (IsPlayerInRangeOfPoint(playerid, 2.5, enter_sys[i][e_coordX], enter_sys[i][e_coordY], enter_sys[i][e_coordZ]))
{
//LoadingStreamer(playerid, 4000);
SetPlayerPosEx(playerid, enter_sys[i][e_int_coordX], enter_sys[i][e_int_coordY], enter_sys[i][e_int_coordZ] + 1.0);
SetPlayerFacingAngle(playerid, enter_sys[i][e_int_coordA]);

SetPlayerInterior(playerid, enter_sys[i][e_interior]);
SetPlayerVirtualWorld(playerid, enter_sys[i][e_virtual_world]);

SetCameraBehindPlayer(playerid);
return 1;
}
}
}
#if defined enters_OnPlayerKeyStateChange // "урезаем" название до 31 символа
enters_OnPlayerKeyStateChange(playerid, newkeys, oldkeys);
#endif
return 1;
}
#if defined _ALS_OnPlayerKeyStateChange // "урезаем" название до 31 символа
#undef OnPlayerKeyStateChange
#else
#define _ALS_OnPlayerKeyStateChange
#endif
#define OnPlayerKeyStateChange enters_OnPlayerKeyStateChange
#if defined enters_OnPlayerKeyStateChange
forward enters_OnPlayerKeyStateChange(playerid, newkeys, oldkeys);
CMD:createenter(playerid, const params[])
{
new
enter_model,
enter_id,
enter_name[MAX_ENTER_NAME],
string[144+1];

if (sscanf(params, "is[36]", enter_model, enter_name)) return SendClientMessageEx(playerid, -1, "/createenter [model] [name]");

for (new i = 0; i != MAX_ENTERS; i ++) if (!strcmp(enter_sys[i][e_name], enter_name, true))
{
format(string, sizeof(string), "Название \"%s\" используется (ID: %d).", enter_name, i);
SendClientMessageEx(playerid, -1, string);
}
enter_id = Enter_Create(playerid, enter_model, enter_name);

if (enter_id == -1) return SendClientMessageEx(playerid, -1, "Сервер достиг лимит динамических пикапов.");

format(string, sizeof(string), "Вы успешно создали пикап под ID: %i | Название: %s.", enter_id, enter_name);
SendClientMessageEx(playerid, -1, string);
return 1;
}

CMD:destroyenter(playerid, const params[])
{
new string[40], number;

//if (player[playerid][pAdmin] < 5) return SendClientMessageEx(playerid, "У вас нет прав использовать эту команду.");

if (sscanf(params, "i", number)) return SendClientMessageEx(playerid, -1, "/destroyenter [enter id]");

if (number < -1 || number >= MAX_ENTERS) return SendClientMessageEx(playerid, -1, "Вы указали недопустимый ID пикапа");

Enter_Delete(playerid, number);
format(string, sizeof(string), "Вы успешно удалили пикап под ID: %i.", number);
SendClientMessageEx(playerid, -1, string);
return 1;
}
CMD:editenter(playerid, const params[])
{
new
enterid,
type[24],
string[128];

//if (player[playerid][pAdmin] < 5)
// return SendClientMessageEx(playerid, -1, ""Error"Недостаточно полномочий.");

if (sscanf(params, "is[24]S()[128]", enterid, type, string))
{
SendClientMessageEx(playerid, -1, "/editenter [id] [params]");
SendClientMessageEx(playerid, -1, "[Параметры]:{FFFFFF} location, interior, model, name");
return true;
}
if (enterid < 0 || enterid >= MAX_ENTERS)
return SendClientMessageEx(playerid, -1, "Вы указали недопустимый ID дома.");

if (!strcmp(type, "location", true))
{
GetPlayerPos(playerid, enter_sys[enterid][e_coordX], enter_sys[enterid][e_coordY], enter_sys[enterid][e_coordZ]);
GetPlayerFacingAngle(playerid, enter_sys[enterid][e_coordA]);

enter_sys[enterid][e_exterior_vw] = GetPlayerVirtualWorld(playerid);
enter_sys[enterid][e_exterior_int] = GetPlayerInterior(playerid);

MySQL_Enter_SaveFloat(enterid, "e_coordX", enter_sys[enterid][e_coordX]);
MySQL_Enter_SaveFloat(enterid, "e_coordY", enter_sys[enterid][e_coordY]);
MySQL_Enter_SaveFloat(enterid, "e_coordZ", enter_sys[enterid][e_coordZ]);
MySQL_Enter_SaveFloat(enterid, "e_coordA", enter_sys[enterid][e_coordA]);
MySQL_Enter_SaveInt(enterid, "e_exterior_vw", enter_sys[enterid][e_exterior_vw]);
MySQL_Enter_SaveInt(enterid, "e_exterior_int", enter_sys[enterid][e_exterior_int]);

Enter_Refresh(enterid);

format(string, sizeof(string), "[ADMIN]: %s изменил местоположение пикапа ID: %i.", player[playerid][pName], enterid);
SendClientMessageEx(playerid, -1, string);
}
else if (!strcmp(type, "interior", true))
{
GetPlayerPos(playerid, enter_sys[enterid][e_int_coordX], enter_sys[enterid][e_int_coordY], enter_sys[enterid][e_int_coordZ]);
GetPlayerFacingAngle(playerid, enter_sys[enterid][e_int_coordA]);

enter_sys[enterid][e_interior] = GetPlayerInterior(playerid);
enter_sys[enterid][e_virtual_world] = GetPlayerVirtualWorld(playerid);

foreach (new i : Player)
{
if (player[i][pProperty_House] == enter_sys[enterid][e_id])
{
SetPlayerPos(i, enter_sys[enterid][e_int_coordX], enter_sys[enterid][e_int_coordY], enter_sys[enterid][e_int_coordZ]);
SetPlayerFacingAngle(i, enter_sys[enterid][e_int_coordA]);

SetPlayerInterior(i, enter_sys[enterid][e_interior]);
SetPlayerVirtualWorld(i, enter_sys[enterid][e_virtual_world]);
SetCameraBehindPlayer(i);
}
}
MySQL_Enter_SaveFloat(enterid, "e_int_coordX", enter_sys[enterid][e_int_coordX]);
MySQL_Enter_SaveFloat(enterid, "e_int_coordY", enter_sys[enterid][e_int_coordY]);
MySQL_Enter_SaveFloat(enterid, "e_int_coordZ", enter_sys[enterid][e_int_coordZ]);
MySQL_Enter_SaveFloat(enterid, "e_int_coordA", enter_sys[enterid][e_int_coordA]);
MySQL_Enter_SaveInt(enterid, "e_interior", enter_sys[enterid][e_interior]);
MySQL_Enter_SaveInt(enterid, "e_virtual_world", enter_sys[enterid][e_virtual_world]);

format(string, sizeof(string), "[ADMIN]: %s изменил точку выхода пикапа ID: %i.", player[playerid][pName], enterid);
SendClientMessageEx(playerid, -1, string);
}
else if (!strcmp(type, "model", true))
{
new new_model;

if (sscanf(string, "i", new_model))
return SendClientMessageEx(playerid, -1, "/editenter [id] [new model]");

enter_sys[enterid][e_model] = new_model;

MySQL_Enter_SaveInt(enterid, "e_model", enter_sys[enterid][e_model]);
Enter_Refresh(enterid);

format(string, sizeof(string), "[ADMIN]: %s изменил модель пикапа ID: %i на %d.", player[playerid][pName], enterid, new_model);
SendClientMessageEx(playerid, -1, string);
}
else if (!strcmp(type, "name", true))
{
new new_name[32];

if (sscanf(string, "s[32]", new_name))
return SendClientMessageEx(playerid, -1, "/editenter [id] [new name]");

enter_sys[enterid][e_name] = new_name;

MySQL_Enter_SaveString(enterid, "e_name", enter_sys[enterid][e_name]);
Enter_Refresh(enterid);

format(string, sizeof(string), "[ADMIN]: %s изменил название пикапа ID: %i на \"%s\".", player[playerid][pName], enterid, new_name);
SendClientMessageEx(playerid, -1, string);
}
return true;
}

Надеюсь, на Вашу помощь и подробное описание, где мои кривые руки использовали что-то неверно, потому что просто скинуть фикс - будет слишком легко, я хочу понять, в чем моя ошибка. Спасибо <3

DeimoS
02.11.2018, 11:02
Ты, конечно, можешь понадеяться, что кто-то потратит определённое количество своего времени, чтоб сначала разобраться в твоём коде, а потом найти ошибку, но я сомневаюсь, что такие люди найдутся. Уж очень большая у тебя система для подобного рода помощи. Тут тебе только заказ исправления системы за деньги может помочь.

Хотя уже то, что ты каждую переменную сохраняешь отдельным запросом, вместо того, чтоб составить один большой запрос - крайне сомнительное решение. Да и для реализации того, что ты задумал, достаточно хранить ID пикапа, а всё остальное уже изменять напрямую в памяти стримера через эти функции:
// Natives (Data Manipulation)

native Streamer_GetFloatData(type, STREAMER_ALL_TAGS id, data, &Float:result);
native Streamer_SetFloatData(type, STREAMER_ALL_TAGS id, data, Float:value);
native Streamer_GetIntData(type, STREAMER_ALL_TAGS id, data);
native Streamer_SetIntData(type, STREAMER_ALL_TAGS id, data, value);
native Streamer_GetArrayData(type, STREAMER_ALL_TAGS id, data, dest[], maxdest = sizeof dest);
native Streamer_SetArrayData(type, STREAMER_ALL_TAGS id, data, const src[], maxsrc = sizeof src);
native Streamer_IsInArrayData(type, STREAMER_ALL_TAGS id, data, value);
native Streamer_AppendArrayData(type, STREAMER_ALL_TAGS id, data, value);
native Streamer_RemoveArrayData(type, STREAMER_ALL_TAGS id, data, value);
native Streamer_GetUpperBound(type);
Тогда и пересоздавать пикап не нужно будет постоянно.
В общем, гораздо проще будет заказать у кого-то систему с нуля, чем ждать, что кто-то подскажет тебе исправление твоей системы, ибо сейчас ты предлагаешь вслепую определить какую-то проблему, которую ты толком не описал (не описал как вызвать баг и т.п.)

Kovshevoy
02.11.2018, 11:13
Ты, конечно, можешь понадеяться, что кто-то потратит определённое количество своего времени, чтоб сначала разобраться в твоём коде, а потом найти ошибку, но я сомневаюсь, что такие люди найдутся. Уж очень большая у тебя система для подобного рода помощи. Тут тебе только заказ исправления системы за деньги может помочь.

Хотя уже то, что ты каждую переменную сохраняешь отдельным запросом, вместо того, чтоб составить один большой запрос - крайне сомнительное решение. Да и для реализации того, что ты задумал, достаточно хранить ID пикапа, а всё остальное уже изменять напрямую в памяти стримера через эти функции:
// Natives (Data Manipulation)

native Streamer_GetFloatData(type, STREAMER_ALL_TAGS id, data, &Float:result);
native Streamer_SetFloatData(type, STREAMER_ALL_TAGS id, data, Float:value);
native Streamer_GetIntData(type, STREAMER_ALL_TAGS id, data);
native Streamer_SetIntData(type, STREAMER_ALL_TAGS id, data, value);
native Streamer_GetArrayData(type, STREAMER_ALL_TAGS id, data, dest[], maxdest = sizeof dest);
native Streamer_SetArrayData(type, STREAMER_ALL_TAGS id, data, const src[], maxsrc = sizeof src);
native Streamer_IsInArrayData(type, STREAMER_ALL_TAGS id, data, value);
native Streamer_AppendArrayData(type, STREAMER_ALL_TAGS id, data, value);
native Streamer_RemoveArrayData(type, STREAMER_ALL_TAGS id, data, value);
native Streamer_GetUpperBound(type);
Тогда и пересоздавать пикап не нужно будет постоянно.
В общем, гораздо проще будет заказать у кого-то систему с нуля, чем ждать, что кто-то подскажет тебе исправление твоей системы, ибо сейчас ты предлагаешь вслепую определить какую-то проблему, которую ты толком не описал (не описал как вызвать баг и т.п.)

Баг в том и заключается, что система ИЛИ не создает пикап (но, в базе есть данные), ИЛИ пикап создается, но когда я жму на клавишу, чтобы перейти по коордам - не срабатывает.

DeimoS
02.11.2018, 12:33
Ну так логируй ID только что созданного пикапа в случае, если он не создаётся. Если ID будет, значит косяк с координатами или виртуальным миром.
То же самое и с действием на кнопку: логируй координаты всех пикапов и смотри координаты того, который должен был сработать, но не срабатывает.

К слову, цикл, который срабатывает на кнопку, хорошо бы снабдить проверкой на виртуальный мир перед тем, как ты координаты проверяешь. Сверить виртуальный мир будет быстрее, чем вызвать IsPlayerInRangeOfPoint. А этим ты приличное число пикапов сразу отсеешь.

Ну и немного субъективщины: имхо, но гораздо удобнее было бы реализовать ту твою команду с редактированием пикапа через диалог. Там можно и текущие значения удобно отобразить, и сразу несколько значений изменить, и отменить изменения, в случае чего.