30.01.2014, 15:23
(
Последний раз редактировалось White_116; 02.08.2014 в 14:24.
)
Добрый день!
Многие задавались вопросом: Как перенести карту(группу объектов) на другое место, чтобы при переносе позиция и повороты объектов относительно объектов сохранилась как в оригинале. Так как это нужда докатилась и до меня, я расскажу вам как это сделать.
Для начала нам нужна самая главная функция, функция крепления объекта к объекту, она будет отвечать за перемещение и поворот относительно главного объекта. Порыскав по форуму мне удалось найти эту функцию.
Автор: Stylock | AttachObjectToObjectEx Расписывать её не стану, по названию уже ясно, аналогом какой функции является.
pawn Код:
AttachObjectToObjectEx(objectid, attachoid, Float:off_x, Float:off_y, Float:off_z, Float:rot_x, Float:rot_y, Float:rot_z)
{
static
Float:sin[3],
Float:cos[3],
Float:pos[3],
Float:rot[3];
GetObjectPos(attachoid, pos[0], pos[1], pos[2]);
GetObjectRot(attachoid, rot[0], rot[1], rot[2]);
cos[0] = floatcos(rot[0], degrees); cos[1] = floatcos(rot[1], degrees); cos[2] = floatcos(rot[2], degrees); sin[0] = floatsin(rot[0], degrees); sin[1] = floatsin(rot[1], degrees); sin[2] = floatsin(rot[2], degrees);
pos[0] = pos[0] + off_x * cos[1] * cos[2] - off_x * sin[0] * sin[1] * sin[2] - off_y * cos[0] * sin[2] + off_z * sin[1] * cos[2] + off_z * sin[0] * cos[1] * sin[2];
pos[1] = pos[1] + off_x * cos[1] * sin[2] + off_x * sin[0] * sin[1] * cos[2] + off_y * cos[0] * cos[2] + off_z * sin[1] * sin[2] - off_z * sin[0] * cos[1] * cos[2];
pos[2] = pos[2] - off_x * cos[0] * sin[1] + off_y * sin[0] + off_z * cos[0] * cos[1];
rot[0] = asin(cos[0] * cos[1]); rot[1] = atan2(sin[0], cos[0] * sin[1]) + rot_z; rot[2] = atan2(cos[1] * cos[2] * sin[0] - sin[1] * sin[2], cos[2] * sin[1] - cos[1] * sin[0] * -sin[2]);
cos[0] = floatcos(rot[0], degrees); cos[1] = floatcos(rot[1], degrees); cos[2] = floatcos(rot[2], degrees); sin[0] = floatsin(rot[0], degrees); sin[1] = floatsin(rot[1], degrees); sin[2] = floatsin(rot[2], degrees);
rot[0] = asin(cos[0] * sin[1]); rot[1] = atan2(cos[0] * cos[1], sin[0]); rot[2] = atan2(cos[2] * sin[0] * sin[1] - cos[1] * sin[2], cos[1] * cos[2] + sin[0] * sin[1] * sin[2]);
cos[0] = floatcos(rot[0], degrees); cos[1] = floatcos(rot[1], degrees); cos[2] = floatcos(rot[2], degrees); sin[0] = floatsin(rot[0], degrees); sin[1] = floatsin(rot[1], degrees); sin[2] = floatsin(rot[2], degrees);
rot[0] = atan2(sin[0], cos[0] * cos[1]) + rot_x; rot[1] = asin(cos[0] * sin[1]); rot[2] = atan2(cos[2] * sin[0] * sin[1] + cos[1] * sin[2], cos[1] * cos[2] - sin[0] * sin[1] * sin[2]);
cos[0] = floatcos(rot[0], degrees); cos[1] = floatcos(rot[1], degrees); cos[2] = floatcos(rot[2], degrees); sin[0] = floatsin(rot[0], degrees); sin[1] = floatsin(rot[1], degrees); sin[2] = floatsin(rot[2], degrees);
rot[0] = asin(cos[1] * sin[0]); rot[1] = atan2(sin[1], cos[0] * cos[1]) + rot_y; rot[2] = atan2(cos[0] * sin[2] - cos[2] * sin[0] * sin[1], cos[0] * cos[2] + sin[0] * sin[1] * sin[2]);
SetObjectPos(objectid, pos[0], pos[1], pos[2]);
SetObjectRot(objectid, rot[0], rot[1], rot[2]);
}
pawn Код:
new W_K,
W_id[MAX_OBJECTS],
W_m[MAX_OBJECTS],
Float:W_x[MAX_OBJECTS],
Float:W_y[MAX_OBJECTS],
Float:W_z[MAX_OBJECTS],
Float:W_rx[MAX_OBJECTS],
Float:W_ry[MAX_OBJECTS],
Float:W_rz[MAX_OBJECTS],
Float:W_d[MAX_OBJECTS];
pawn Код:
CreateObjectEx(m, Float:x=0.0, Float:y=0.0, Float:z=0.0, Float:rx=0.0, Float:ry=0.0, Float:rz=0.0, Float:d=300.0)
//Ищет координаты относительно основного объекта.
{
if(W_K == 0)
{
m=18980;
W_x[0]=x;
W_y[0]=y;
W_z[0]=z;
rx=0.001;//фикс погрешности float 0.9999999999
ry=0.0;
rz=0.0;
}
else
{
W_x[W_K]=x-W_x[0];
W_y[W_K]=y-W_y[0];
W_z[W_K]=z-W_z[0];
rx+=0.001;
}
W_m[W_K]=m;
W_d[W_K]=d;
W_rx[W_K]=rx;
W_ry[W_K]=ry;
W_rz[W_K]=rz;
m=W_id[W_K++]=CreateObject(m, x, y, z, rx, ry, rz, d);
return m;
}
Для того, чтобы визуально было видно перемещение всей карты, прикрепим все объекты к управляющему, далее вызываем "редактор" объекта.
Сохранение производим после сохранения позиции карты в "редакторе".
pawn Код:
public OnPlayerCommandText(playerid, cmdtext[])
{
if(strcmp(cmdtext, "/edit", true)==0)
{
for(new k=1; k < MAX_OBJECTS; k++)if(W_id[k])
AttachObjectToObject(W_id[k], W_id[0], W_x[k], W_y[k], W_z[k], W_rx[k], W_ry[k], W_rz[k]);//Приатачим все объекты к основному.
return EditObject(playerid,W_id[0]);//Войдём в режим редактирования.
}
if(strcmp(cmdtext, "/saveo", true)==0)
{
if(fexist("MovedObject.pwn"))fremove("MovedObject.pwn");//Удалим файл если он есть.
new File:example=fopen("MovedObject.pwn", io_append);//Создадим файл и откроем для записи.
if(example)//Если нет ошибок.
{
new str[128],Float:x=0.0, Float:y=0.0, Float:z=0.0, Float:rx=0.0, Float:ry=0.0, Float:rz=0.0;
for(new k=1; k < MAX_OBJECTS; k++)if(W_id[k])//Бежим по всем объектам.
{
GetObjectPos(W_id[k], x,y,z);//Получим координаты.
GetObjectRot(W_id[k], rx,ry,rz);//Получим ротацию.
format(str,sizeof(str),"CreateObject(%d, %0.3f, %0.3f, %0.3f, %0.3f, %0.3f, %0.3f, %0.3f);\r\n",W_m[k],x,y,z,rx,ry,rz,W_d[k]);
fwrite(example, str);//Запишем строку.
}
fclose(example);//Закроем файл.
}
else return SendClientMessage(playerid,0xFF4444FF,"Файл не создан!");
return SendClientMessage(playerid,0xFF4444FF,"Объекты сохранены. srv/scriptfiles/MovedObject.pwn");
}
return 0;//Команды небыли выполнены, бежим дальше.
}
-При состоянии EDIT_RESPONSE_UPDATE нам не нужно вызывать AttachObjectToObjectEx, так как мы уже прикрепили объекты к управляющему, и там всё прекрасно и плавно движется, чего нельзя сказать при применение AttachObjectToObjectEx.
-При состоянии EDIT_RESPONSE_CANCEL сделан сброс управляющего объекта на изначальные координаты и поворот. Открепляется объекты и вызывается AttachObjectToObjectEx для корректировки позиции и поворота объектов.
-При состоянии EDIT_RESPONSE_FINAL выполняется сохранение позиции управляющего объекта.
Открепляется объекты и вызывается AttachObjectToObjectEx для корректировки позиции и поворота объектов. Теперь уже можно производить сохранение всей карты.
pawn Код:
public OnPlayerEditObject(playerid, playerobject, objectid, response, Float:fX, Float:fY, Float:fZ, Float:fRotX, Float:fRotY, Float:fRotZ)
{
if(!IsValidObject(objectid)) return 0;//Объекта не существует - выйдем.
if(playerobject)return 0; //объект не глобальный - выйдем.
if(response == EDIT_RESPONSE_UPDATE)return 0;//Игрок подвинул объект - выйдем.
else if(response == EDIT_RESPONSE_FINAL)
{
//Сохраним координаты
W_x[0]=fX;
W_y[0]=fY;
W_z[0]=fZ;
W_rx[0]=fRotX;
W_ry[0]=fRotY;
W_rz[0]=fRotZ;
SetObjectPos(objectid, fX, fY, fZ);//Установим перемещение
SetObjectRot(objectid, fRotX, fRotY, fRotZ);//Установим поворот
}
else if(response == EDIT_RESPONSE_CANCEL)
{
SetObjectPos(objectid, W_x[0], W_y[0], W_z[0]);//Отменим перемещение
SetObjectRot(objectid, W_rx[0], W_ry[0],W_rz[0]);//Отменим поворот
}
for(new k=1; k < MAX_OBJECTS; k++)if(W_id[k])//Прогон по всем объектам.
{
AttachObjectToObject(W_id[k], W_id[k],0.0,0.0, 0.0, 0.0, 0.0, 0.0);//Отцепим объект от системного.
AttachObjectToObjectEx(W_id[k], W_id[0], W_x[k], W_y[k], W_z[k], W_rx[k], W_ry[k], W_rz[k]);//Установим позицию и ротацию как при склеивании.
}
return 1;
}
pawn Код:
public OnFilterScriptExit()
{
for(new k; k < MAX_OBJECTS; k++)if(W_id[k])DestroyObject(W_id[k]),W_id[k]=0;//Удалим все созданные объекты
return 1;
}
После того как были изменены координаты управляющего объекта можно приступить к добавлению своих.
Внимание, так как используются глобальные объекты, стоит учесть лимиты и нельзя допустить чтобы они их превышали.. Рекомендую переносить объекты на чистом(стандартном сервере).
pawn Код:
public OnFilterScriptInit()
{
/*============================================================================*\
Системный объект!1!11!!!!1!
\*============================================================================*/
//Можно изменить только координаты.
//Координаты дожны быть по середине группы объектов.
CreateObjectEx(18980, 2048.0,1336.0,10.0); //Основной объект.
/*============================================================================*\
Дальше вписываем ваши объекты
\*============================================================================*/
CreateObjectEx(19057,2052.0,1340.0,10.0,45.0,-45.0,353.4901); //
CreateObjectEx(19057,2044.0,1340.0,10.0,45.0,45.0,5.3968); //
CreateObjectEx(19057,2044.0,1332.0,10.0,45.0,-45.0,178.9618); //
CreateObjectEx(19057,2052.0,1332.0,10.0,45.0,45.0,193.3753); //
return 1;
}
Скриншоты: