Перейти к содержанию

Добро пожаловать на проект
Weekly Open Games

Weekly Open Games — это проект для людей, которым интересен хардкорный тип игры. Мы стараемся максимально эффективно использовать структуру, слабые и сильные стороны, а также технику и вооружение различных сторон конфликта, но не ставим перед собой цель провести 100% сбалансированного боестолкновения. Командная игра, командное взаимодействие — фундамент нашего проекта.
О проекте WOG Как начать играть Правила серверов
ToxaSM

Вопросы по созданию МП-миссий

Рекомендуемые сообщения

Просьба к умеющим в Local/Global проверить корректность работы следующих скриптов применительно к мультиплееру A3:

1) Создание новой локации и метки-подписи на карте.
В редакторе работает

//код для вставки в файл init.sqf
_myNewLocation1 = createLocation ["NameLocal", [12842,16680,90.9832], 200, 200];
_myNewLocation1 setText "FOB Fenix";

2) Замена встроенных в карту объектов по их ID (например, зданий) на другие объекты (например, бункер).
В редакторе работает

//Empty - необходимый объект, например Бункер ==> init field:
myNewObj1 = (position this nearestobject 673184);
this setPos [(getPos myNewObj1 select 0), (getPos myNewObj1 select 1), 0];
this setDir (getDir myNewObj1);
myNewObj1 hideObjectGlobal true; myNewObj1 allowDamage false;

3) Удаление встроенных в карту объектов по их ID (например, зданий) при помощи замены на невидимый HeliPad.
В редакторе работает

//Empty - Objects - H(Invisible) ==> init field:
this enableSimulation false; this allowDamage false;
obj = [0,0,0] nearestObject 673047; obj hideObjectGlobal true;
obj = [0,0,0] nearestObject 673045; obj hideObjectGlobal true;//перечисляем удаляемые объекты
//или альтернативный код
this enableSimulation false; this allowDamage false;
obj = (getPos this) nearestObject 673047; obj hideObjectGlobal true;
obj = (getPos this) nearestObject 673045; obj hideObjectGlobal true;//перечисляем удаляемые объекты

4) Добавление на карту объектов, которых нет в редакторе, по их класс-нейму.
В редакторе работает

//Game Logic - Objects - Game Logic ==> init field:
tower = createVehicle ["Land_Cargo_Tower_V1_F", getPos this, [], 0, ""];  
tower setDir 190; tower call BIS_fnc_boundingBoxMarker;
//последняя функция должна добавлять маркер объекта на карту

5) Добавить неуничтожаемость встроенному объекту на карте.
В редакторе вроде бы работает

//разместить юнит Game Logic над необходимым объектом
//Game Logic - Objects - Game Logic ==> init field:
(nearestBuilding this) allowDamage false;

6) Удаление встроенных в карту объектов по их ID (например, зданий) посредством их разрушения, а затем удаления их руин.
Не получается заставить работать в редакторе

//код для вставки в файл init.sqf
private ["_tower1","_ruins1"];
_tower1 = [0,0,0] nearestObject 523286;
_tower1 setDamage 1;
sleep 10;
_ruins1 = nearestObject [[14520,16705,18],"Land_Cargo_Tower_V1_ruins_F"];
deleteVehicle _ruins1;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

воот эт портянка :)

Проверять лениво, но научу как сделать (я считаю эту позицию правильной).

Смотри разбиваешь все свои команды на global/local (с помощью wiki смотришь какой эффект от операции для сервера и клиента картинки ниже)

в init sqf делаешь 2 блока кода

1 блок кода - код который выполняет ТОЛЬКО сервер (тут все твои команды и функции в итоге которые дают effects_global.gif)

if (isServer) then {
sleep 0.01;
//твой код содержащий ТОЛЬКО глобальный эффект
//или код для обработки скриптов и прочего говнокода что ты придумал
};

2 блок - БЛОК кода ТОЛЬКО ДЛЯ клиентов (тут все твои команды и функции в итоге которые даютeffects_local.gif локальный эффект)

if (!isDedicated) then {
sleep 0.01;
//твой код содержащий ТОЛЬКО локальный эффект
//и евент хендлеры и прочее говно для синхронизации с сервером.
};

В чем суть фокуса, глобальный эффект уже подразумевает синхронизацию действия со всеми клиентами и сервером, а т.к в большинстве случаев на сервере больше ресурсов для обработки (математических, логических, триггерных) ситуаций, все эти задачи правильнее всего "вешать" на сервер. А клиенту давать или addEventHandler (в случае если эффект локальный effects_local.gif) или ничего (в случаях если это так надо или глобального эффекта effects_global.gif ).

Ну собственно вот и вся магия. (Поправьте если не так)

Изменено пользователем StDIABLO

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты


5) Добавить неуничтожаемость встроенному объекту на карте. В редакторе вроде бы работает //разместить юнит Game Logic над необходимым объектом //Game Logic - Objects - Game Logic ==> init field: (nearestBuilding this) allowDamage false;

 

просто обзываешь здание на карте и в юнит скф (в разделе для сервера) 

<название дома> allowDamage false;

Простое правило -> меньше обьектов не нужных для клиентов - лучше работает. 

В твоем случае

1)клиенту совершенно не нужен этот объект гейм логик для работы.

2) все что написано в разделе init field ->выполняется всеми клиентами, а т.к эффект уже глобальный - это можно сделать только 1 раз но на сервере. и всем будет хорошо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4) Добавление на карту объектов, которых нет в редакторе, по их класс-нейму. В редакторе работает //Game Logic - Objects - Game Logic ==> init field: tower = createVehicle ["Land_Cargo_Tower_V1_F", getPos this, [], 0, ""];   tower setDir 190; tower call BIS_fnc_boundingBoxMarker; //последняя функция должна добавлять маркер объекта на карту

 

да это работает но это совершенно бессмыслено для клиента. лучше или:

 

1)или поставить 101 editor http://www.armaholic.com/page.php?id=20821 (показывает все равно не все объекты пришлось доделывать напильником)

2)или менять класс прямо через текстовый редактор в mission.sqm

3)или создавать объекты уже не в редакторе, а при запуске миссии самим сервером. (Благо эффект от createVehicle глобальный) самая лучшая реализация для расстановки ВСЕГО НА КАРТЕ, кроме самих клиентов)

 

ps не забывай удалять из памяти ненужные объекты

//Game Logic - Objects - Game Logic ==> init field:
tower = createVehicle ["Land_Cargo_Tower_V1_F", getPos this, [], 0, ""];  
tower setDir 190; 
tower call BIS_fnc_boundingBoxMarker; //последняя функция должна добавлять маркер объекта на карту
deleteVehicle this; //вроде так
Изменено пользователем StDIABLO

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6) Удаление встроенных в карту объектов по их ID (например, зданий) посредством их разрушения, а затем удаления их руин.

Во первых почему не работает.

 

setDamagearguments_global.gifeffects_global.gif

 

Аргумент должен быть глобальным, а он у тебя вроде как локальный (приватный)  _tower1

код ниже должен сработать:

([0,0,0] nearestObject 523286) setDamage 1;

тоже самое и с deleteVehicle.

 

А почему  сразу объект не удалить, напомни?

Код ниже не работает?

deleteVehicle ([0,0,0] nearestObject 523286); //код не пашет :( ниже обновленная версия

  или 

([0,0,0] nearestObject 523286) enableSimulation false; 
([0,0,0] nearestObject 523286) allowDamage false;
([0,0,0] nearestObject 523286) hideObjectGlobal true;//должно выполниться в блоке isServer

(прост нет армы на работе прочекать не могу)

Изменено пользователем StDIABLO

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3) Удаление встроенных в карту объектов по их ID (например, зданий) при помощи замены на невидимый HeliPad. 

 

Это все в зону isServer. Но ты не удаляешь объект, а делаешь формально его невидимым. Ты можешь обратно его в любой момент времени "ВКЛЮЧИТЬ", такч это не замена на невидимый хелипад.

 

Но запомни еще одно если есть возможность не создавать переменную - пользуйся ей. Исключений тут оч мало.

т.е код:

obj = [0,0,0] nearestObject 673047; obj hideObjectGlobal true;

лучше (будет меньше занимать в памяти) будет таким

([0,0,0] nearestObject 673047) hideObjectGlobal true;

1) Создание новой локации и метки-подписи на карте.

 

Все в блок (!isDedicated), возможно тебе понадобятся условия проверки на сторону (side player)  возможно не всем надо знать о зоне.

 

 


2) Замена встроенных в карту объектов по их ID (например, зданий) на другие объекты (например, бункер). 

 

Смотри, лучше поставить вопрос не так, не замена, а удаление ненужных мне объектов и расстановка нужных по этим же координатам.

Удаление/сокрытие ненужных по ID есть выше, ну а расстановкой новых объектов на их места - справится и обычный редактор.

 

Просто запомни init объекта читают все (и сервер и клиенты - лучшая синхронизация), а надо чтобы читал сервер (лучшее время работы,меньше лагов). Вот и смотри что тебе надо синхронизацию улучшить или лагодром устранить.

Изменено пользователем StDIABLO

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

просто обзываешь здание на карте и в юнит скф (в разделе для сервера)

<название дома> allowDamage false;

 

А как правильнее это сделать для встроенного объекта? В init.sqf сначала создаем локальную переменную, а потом с ней выполняем действия?

_delObj1 = [0,0,0] nearestObject 673047;
_delObj1 allowDamage false;
//или так
//встречал мнение, что (getPos this) лучше чем [0,0,0]
_delObj1 = (getPos this) nearestObject 673047;
_delObj1 allowDamage false;
Изменено пользователем Sandy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2)или менять класс прямо через текстовый редактор в mission.sqf

Хорошая идея. Нужно будет попробовать.

 

 


ps не забывай удалять из памяти ненужные объекты
у deleteVehicle this; //вроде так

Вот здесь не понял. А это не удалит глобально объект, который мы специально создаем ?

Изменено пользователем Sandy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот здесь не понял. А это не удалит глобально объект, который мы специально создаем ?

Код глянь внимательно, и думай как компилятор.

 

Ты создал глобальный объект (в нашем случае это объект геймлогик) сам он невидим ни для сервера, ни для клиента. И есть в памяти и у сервера и у клиента.

В его ините прописал создание другого объекта. Он также создался.  Объект гейм логик закончил свою работу и не нужен НИ СЕРВЕРУ НИ КЛИЕНТУ и может быть удален. В ООП есть всякие деструкторы для этих целей. Тут такого я не находил и приходится все чистить руками.

 

ps про JIP не говорю пока, для JIP надо функции делать чтобы синхронизация между сервером и клиентом JIP была во время соединения.

Например вешать пару функций которые делаются по умолчанию только на сервере на JIP клиента. Т.о . синхронизировав все данные. (Об этом потом)

 

 

А как правильнее это сделать для встроенного объекта? В init.sqf сначала создаем локальную переменную, а потом с ней выполняем действия?

Что ты подразумаваешь под встроенным? Созданный сервером или редактором?

 

 

встречал мнение, что (getPos this) лучше чем [0,0,0]

 

Я честно не знаю что лучше, пока не посмотрю стек армы, как хранятся переменные и прочее.

 

смотри код getPos this создает тебе массив чисел с плавающими точками. например [-25.1412341234,2013.452234,10]

Технически, я уверен (без учета действий компилятора) что этот массив занимает СТОЛЬКО же  памяти что и [0,0,0] (Есть бит для знака, биты для обозначения положения плавающей точки, сами числа см. примеры хранения чисел в памяти)

 

т.е в памяти [-25.1412341234,2013.452234,10]

хранится 3 числа где каждое число составляет из себя пакет данных.

[0,0,0] это те же 3 пакета данных, только у каждого из пакетов  нули.

 

Тут начинается работа компиляторов, и анализатора кода, такие моменты (в нормальных компиляторах) отслеживаются и одинаковые константы "схлопываются" до уровня - одна константа и куча ссылок на нее. И в итоге получается массив [0, указатель на 0, указатель на 0] и в памяти получается так что [0,0,0] почти столько же занимает памяти что и [0] (еще немного данных на указатели, но указатель это не число оно меньше занимает памяти). А если можно сожрать памяти меньше зачем ее брать больше? Мы ж не гугл хром :)

 

Я конечно не уверен как сделан компилятор в A3, но это правило хорошего тона такую фичу встраивать в компиляторы. И даже если этой фичи нет, стоит так писать (мб завтра эта фича появится и код не надо будет переписывать под это).

Изменено пользователем StDIABLO

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

[member=StDIABLO], Спасибо за обстоятельные ответы. Осмысление их у меня, новичка, займет еще какое-то время. :)

 

встречал мнение, что (getPos this) лучше чем [0,0,0]

 

Ссылку на это мнение пока не могу найти, но читал буквально вчера на каком-то англоязычном форуме. Там контекст касался конкретно команды nearestObject ID и о том, что, если я правильно понял, поиск объекта на больших картах, по этому мнению, занимает меньше времени, если задавать (getPos this) , а не [0,0,0]. Т.е. речь шла не об объеме памяти, а о скорости выполнения команды.


Что ты подразумаваешь под встроенным? Созданный сервером или редактором?

Я имел в виду встроенные в карту объекты.

Изменено пользователем Sandy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну это то да, если уж хооочется поставить:

Это будет лучше :)

_world = getWorld;_centerPosition = getArray (configfile >> "CfgWorlds" >> _world>> "centerPosition");
_centerPosition nearestObject 673047;

Кароч снос говна с карты по ID
только что проверил - все пашет как часы


init.sqf

if (isServer) then{
sleep 0.1; //обязательно нужная команда работает как waitUntil {time>0}; 
{([0,0,0] nearestObject _x) setDammage 1} foreach [192112,192155]; //в массив пили свои объекты, вместо [0,0,0] можешь впилить то что я написал выше с _centerPosition
};
Изменено пользователем StDIABLO

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

[member=StDIABLO],

Обнаглею и продолжу задавать нубские вопросы.

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

//init.sqf
if (isServer) then{
sleep 0.1;
{([0,0,0] nearestObject _x) setDammage 1} foreach [192112,192155];
};

Правильно ли я читаю твой код?

_world = getWorld; //создаем переменную и присваиваем ей значение командой, которая возвращает название острова, например, Altis
_centerPosition = getArray (configfile >> "CfgWorlds" >> _world>> "centerPosition"); //создаем переменную и присваиваем ей значение командой, которая вытягивает координаты "центра острова" в виде массива из файла конфига по адресу (configFile/"CfgWorlds"/Altis/"centerPosition")
_centerPosition nearestObject 673047;//возвращает объект с указанным ID после неограниченного поиска от указанных координат

И что с этим делать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

[member=Sandy],
1 часть, все верно это разрушение объектов.
Этот код должен удалить объекты.

//init.sqf
if (isServer) then{
sleep 0.1;
{deleteVehicle ([0,0,0] nearestObject _x)} foreach [192112,192155]; //код не пашет :( ниже обновленная версия
};

Просто занимался разрушением на 1 из мисок прост копирнул код. Тебе самое главное получить объект. А что ты с ним делать будешь всеравно.

По поводу 2 части.

Да понимание кода правильное
надо просто попробовать такой код ( - 2 переменных бесполезных)

_obj = (getArray (configfile >> "CfgWorlds" >> getWorld >> "centerPosition")) nearestObject 673047;//возвращает объект с указанным ID начиная поиск от центра карты (потенциально увеличение скорости)

и да чтобы получить объект нужен приемник :) (в моем случае _obj).

 

Смотри, про скорость этого скрипта.

 

предположем у тебя объект гдето не посередине карты.  nearestObject работает по кругу, [0,0,0] конечноже очень далеко от середины или до другого конца карты. а центр карты равноудален от всех объектов.

Изменено пользователем StDIABLO

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты


Этот код должен удалить объекты.

К сожалению, судя по описанию, команда deleteVehicle не может удалять встроенные в карту объекты. Поэтому я и пытался найти/придумать костыли. Костыли вроде бы нашел, но пока не умею проверять их работоспособность кроме как в редакторе. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

[member=Sandy], Пардоньте  незнал (да и никогда не пытался удалить объекты с карты.

 

Код ниже будет работать тогда

//init.sqf
if (isServer) then {
sleep 0.1;
{
_tmpobj = [0,0,0] nearestObject _x; //начал использовать переменную т.к возможно вычисления будут медленнее чем использовать эту переменную
//_tmpobj enableSimulationGlobal false;
//_tmpobj allowDamage false;
//_tmpobj hideObjectGlobal true;
//_tmpobj=nil; //освобождаем память мы же няшки и не гугл хром 
//т.к hideObjectGlobal уже отключает коллизию можно не парится с кодом выше
([0,0,0] nearestObject _x) hideObjectGlobal true; // вот и все
} foreach [192112,192155];
};
Изменено пользователем StDIABLO

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

//т.к hideObjectGlobal уже отключает коллизию можно не парится с кодом выше

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

if (isServer) then {
sleep 0.1;
{
_tmpobj = [0,0,0] nearestObject _x;
_tmpobj enableSimulationGlobal false;
_tmpobj allowDamage false;
_tmpobj hideObjectGlobal true;
_tmpobj=nil;
} foreach [673154,673184];
};

Но остается еще одна проблема - от встроенного в карту объекта остается его маркер на карте. Полагаю, его также можно как-то скрыть, например, чем-то типа кода ниже, но как к нему обратиться, как получить имя маркера встроенного в карту объекта?

if (isServer) then {
sleep 0.1;
{
deleteMarker _x;
_x setMarkerAlpha 0;
} foreach ["boundingBoxMarker_673154", "boundingBoxMarker_673184"];
};

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

[b][member=Sandy][/b],

 


Нет, лучше все-таки твой первоначальный вариант, т.к. простое скрытие объекта не делает его неуязвимым. 

 

Как можно уничтожить то, во что невозможно попасть (колизии нет), хотя мб фаб кинуть прям под объект .

 

В любом раскладе код  должен быть таким тогда.

if (isServer) then {
sleep 0.1;
{
_tmpobj = [0,0,0] nearestObject _x;
//_tmpobj enableSimulationGlobal false;//ненужно, это делает hideObj
_tmpobj allowDamage false;
_tmpobj hideObjectGlobal true;
_tmpobj=nil;
} foreach [673154,673184];
};

По поводу второго, пока идей у меня нет :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как можно уничтожить то, во что невозможно попасть (колизии нет), хотя мб фаб кинуть прям под объект

К сожалению, именно так, невидимые, но не неуязвимые. Например, Land_Cargo_Tower_V1_F, встроенная в карту складывается с 3 ракет от Pawnee и на месте казалось бы пустого места спавнятся руины.  :( Можешь представить, как это выглядит, если на это место ты до этого поставил другой объект.

Изменено пользователем Sandy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

[b][member=Banzai][/b], [b][member=StDIABLO][/b],

Пример кода для переноса встроенных в карту объектов при помощи attachTo или setPos можете накидать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Блин ну яж не думал что проверять будешь :) чисто экспромтом без армейки написал :)

 

да не пашет ни аттач ни setPos, такчто юзай проверенное (hideobj)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как у Ми-24В (ФАБ-250) убрать ПТУРы? this removeWeapon "ACE_AT9Launcher_Mi28" не помогает  :unsure:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×

Важная информация

Мы разместили cookie-файлы на ваше устройство, чтобы помочь сделать этот сайт лучше. Вы можете изменить свои настройки cookie-файлов, или продолжить без изменения настроек.